Checking that an Extensible Storage Schema exists before retrieving it's fields

991 views Asked by At

I have used an if statement to check if the method retrieving the schema is null, this is in a separate form that contains the checkedListBox to populate. The code is below and I have marked the conditional that checks for this. My question is; What is the most effective method to ensure that each time the revit add-in is run in a new .rvt file, the schema record already exists before attempting to retrieve a schema? When things go awry a null reference error occurs when trying to access an empty schema.

           //CheckedListBox for filter01 this exists in the form and calls the main 
           class function to retrieve the record.
                checkedListBox1.DataSource = WS.categoryList(rvtDoc, intSwitch = 1);
                Filter01_CategoryList = new List<BuiltInCategory>();


                **if (WS.retSchemaBICMethod(rvtDoc) != null)**
                {
                    TaskDialog.Show("Schema 1 ", " exists");
                    Filter01_CategoryList = WS.retSchemaBICMethod(rvtDoc);
                }
                else
                {
                    TaskDialog.Show("Schema 1 "," has not been created");

                    //Update stored schema field values 
                    inputBIC = checkedListBox1.CheckedItems.Cast<BuiltInCategory>
                    ().ToList<BuiltInCategory>();
                    WS.getSetBIC(rvtDoc, inputBIC);
                    WS.storeSchema(rvtDoc, WS.projectInfoElement, inputBIC,
                    out WS.retrieveBIC);

                    //set checkedlistbox 1
                    Filter01_CategoryList = WS.retSchemaBICMethod(rvtDoc);

                }


       //this code returns the retrieved schema from the main class
    public List<BuiltInCategory>retSchemaBICMethod(Document doc)
    {

        Element piElement = projectInfoFilter(doc);

            // Read back the data from ProjInfo
            Entity retrievedEntity = piElement.GetEntity(Schema.Lookup(schemaGuid));
            IList<int> retrievedData = retrievedEntity.Get<IList<int>>
            (Schema.Lookup(schemaGuid).GetField("BuiltInCatIds"));


            //cast int list back to built-in category list
            retSchemaBIC = retrievedData.Cast<BuiltInCategory>
            ().ToList<BuiltInCategory>();

        return retSchemaBIC;
    }
3

There are 3 answers

0
sweetfa On

The GUID will most likely be different for each Revit project.

It is unclear how you are providing the guid to your retSchemaBICMethod, so it would seem that this is most likely the cause of your issue.

I would take the Schema.Lookup out of a GetEntity call and first check you have a valid value because I suspect that is where your null reference occurs.

I also believe there are issues with the way Revit handles multiple documents and extensible storage. I have had a number of issues occur where a second document is opened and have lodged a bug report with Revit on the issue.

0
Troy G On

To check if a schema exists or not I use the following where name is the name of your Schema. If you use != null it will produce an error at runtime.

Schema s = Schema.ListSchemas().FirstOrDefault(q => q.SchemaName == name);
if (s == null)
{
    // no schema found, create one
}
else
{
    // schema found, use it
}
0
Mah Noor On

To retrieve field data, you have to check that extensible storage schema exist or not. For this you have to understand the whole structure first.

Data Storage -> Schema GUID -> Schema -> Entity -> Field

First you have to check that Data storage exist or not. You can check through FilteredElementCollector.

FilteredElementCollector collector = new FilteredElementCollector(doc);
        var dataStorage = collector.OfClass(typeof(DataStorage)).FirstElement();

        if (dataStorage == null)
        {
            TaskDialog.Show("No data storage found");
            return null;
        }

Every schema has unique GUID. Retrieve GUID against every schema stored in the project.

IList<Guid> SchemaGuids = dataStorage.GetEntitySchemaGuids();

Now you can get the schema by Schema.Lookup(guid) method. After getting schema you can easily get entities stored in the schema and their values.

 foreach (Guid guid in SchemaGuids)
        {
            Schema schema = Schema.Lookup(guid);
            Entity entity = dataStorage.GetEntity(schema);
            tokenValue = entity.Get<string>("Token");
        }