EC CRUD Operations With Native And Managed DgnEC APIs

This blog demonstrates how to use DgnEC native and managed API’s for following:

  1. Locate and load schema
  2. Create EC instances and relationships
  3. Read EC instances and relationships
  4. Update EC instances and relationships
  5. Delete EC instances and relationships

Sample ECSchema

Following is the ECSchema used to perform EC related CRUD operations:

<?xml version="1.0" encoding="utf-8"?>
<ECSchema schemaName="Simple" nameSpacePrefix="demo" version="01.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.2.0">
  <ECClass typeName="Widget" isDomainClass="True">
    <ECProperty propertyName="Manufacturer" typeName="string" />
  </ECClass>
  <ECClass typeName="Gadget" isDomainClass="True">
    <ECProperty propertyName="Manufacturer" typeName="string" />
  </ECClass>
  <ECRelationshipClass typeName="WidgetHasGadgets" description="WidgetHasGadgets" isDomainClass="True" strength="referencing" strengthDirection="forward">
    <Source cardinality="(1,1)" roleLabel="has Gadgets" polymorphic="False">
      <Class class="Widget" />
    </Source>
    <Target cardinality="(1,N)" roleLabel="are held by Widget" polymorphic="False">
      <Class class="Gadget" />
    </Target>
  </ECRelationshipClass>
</ECSchema>

API’s to Locate and load schema

Following are the APIs used to locate schema and import it to Dgn File:

  • Native API to read and import schema:

//Read schema from xml file
static ECSchemaPtr s_ecSchema;
DgnModelR dgnModel = dgnECNativeCrudExample.GetDefaultModel();
DgnFileP dgnFile = dgnModel.GetDgnFileP();
SchemaReadStatus schemaReadStatus = dgnECManager.ReadSchemaFromXmlFile(s_ecSchema, dirName.c_str(), dgnFile);

//Import schema to dgn file
//isExternalSchema is set to false meaning ECSchema is stored in the file
SchemaImportStatus schemaImportStatus = dgnECManager.ImportSchema(*s_ecSchema, *dgnFile,false);

  • Managed API to locate and import schema:

//Locate Schema using schema locator
static IECSchema ecSimpleSchema;
//schemaSearchPath is the path of schema file
IECSchemaLocater searchLocater = new SearchPathSchemaFileLocater(schemaSearchPath);
ECObjects.AddSchemaLocater(searchLocater);
ecSimpleSchema = ECObjects.LocateSchema(schemaName, SchemaMatchType.Exact, null, null);

//Import Schema to dgn file
//ImportSchemaOptions with true value represents external schema
SchemaImportStatus schemaImportStatus = dgnECManager.ImportSchema(ecSimpleSchema, activeDgnFile, new ImportSchemaOptions(true));

API’s to Create EC instances and relationships

Following are the APIs used to Create EC instances and establish relationship between EC instances:

  • Native API to Create EC instances and relationships

//API's to create ECInstances and attach to line element
static DgnElementECInstancePtr s_widgetInstance;
//Create line element
ElementHandle s_widget = dgnECNativeCrudExample.CreateLine(dgnModel, 0, 0, -100, 100);
//Get a ECClass by name within the context of this schema.
ECClassP ecClass = s_ecSchema->GetClassP(dgnECNativeCrudExample.m_schemaWidget);
//Enable the creation of ECInstances of a particular ECClass within a dgn file.
DgnECInstanceEnablerP widgetEnabler = DgnECManager::GetManager().ObtainInstanceEnabler(*ecClass, dgnFile);
//Gets a StandaloneECInstance to be used as a template when creating new persistent ECInstances.
StandaloneECInstanceR wipInstance = widgetEnabler->GetSharedWipInstance();
//Set a value to property of ECInstance
wipInstance.SetValue(m_propertyName, ECValue(L"ACME Engineering"));
//Create a ECInstance on a line element
DgnECInstanceStatus status = widgetEnabler-> CreateInstanceOnElement(&s_widgetInstance, wipInstance, s_widget);

//API's to create relationship between ECInstances
static IDgnECRelationshipInstancePtr s_createdRelationship;
//Get a relationship class 
ECRelationshipClassP ecWidgetHasGadgetClass = dynamic_cast<ECRelationshipClassP>(s_ecSchema->GetClassP(m_relationship));
//Obtain DgnECRelationshipEnabler for relationship class
DgnECRelationshipEnablerP relationshipEnabler = DgnECManager::GetManager().ObtainDgnECRelationshipEnabler(ecWidgetHasGadgetClass-> GetSchema().GetName().c_str(), ecWidgetHasGadgetClass->GetName().c_str(), dgnFile);
//Create relationship between ECInstances
BentleyStatus status = relationshipEnabler-> CreateRelationship(&s_createdRelationship, *s_widgetInstance, *s_gadgetInstance);

  • Managed API to Create EC instances and relationships

//API's to create ECInstances and attach to line element
static IDgnECInstance widgetInstance;
static IDgnECInstance gadgetInstance;
//Create line element
LineElement s_widgetLine = CreateLine(0, 0, -100, 100);
//Get a ECClass by name within the context of this schema.
IECClass ecClass = ecSimpleSchema.GetClass(schema_widget);
//Enable the creation of ECInstances of a particular ECClass within a dgn file
DgnECInstanceEnabler widgetEnabler = dgnECManager.ObtainInstanceEnabler(activeDgnFile, ecClass);
ECDInstance widgetWipInstance = widgetEnabler.SharedWipInstance;
//Set a value to property of ECInstance.
widgetWipInstance.SetAsString(property_Name, "ACME Engineering");
//Creates an ECInstance on a line element.
widgetInstance = widgetEnabler.CreateInstanceOnElement(s_widgetLine, widgetWipInstance, false);

//API's to create relationship between ECInstances
static IECRelationshipInstance relationshipInstance;
//Get a relationship class
IECRelationshipClass widgetHasGadgetRelationshipClass = ecSimpleSchema.GetClass(widgetHasGadgetClassName) as IECRelationshipClass;
//Obtain DgnECRelationshipEnabler for relationship class
DgnECRelationshipEnabler relationshipEnabler = dgnECManager.ObtainDgnECRelationshipEnabler(activeDgnFile, widgetHasGadgetRelationshipClass);
//Create relationship between ECInstances
relationshipInstance = relationshipEnabler.CreateRelationshipOnElement(widgetInstance, gadgetInstance);

API’s to Read EC instances and relationships

Following are the APIs used to Read EC instances and relationship between EC instances:

  • Native API to Read EC instances and relationships

//API's to read ECInstances
//Construct an ECQuery to search for instances of a ECClass
ECQueryPtr query = ECQuery::CreateQuery(*ecWidgetClass);
query->SetSelectProperties(true);
//Create a scope which finds instances accessible through a dgn file
//FindInstancesScopeOption Describes the underlying type on which an instance can be persisted
FindInstancesScopePtr scope = FindInstancesScope::CreateScope(dgnFile, FindInstancesScopeOption(DgnECHostType::Element));
//Find DgnElementECInstances in a dgn file using the supplied scope and query
DgnECInstanceIterable instances = DgnECManager::GetManager().FindInstances(*scope, *query);
//For each ECInstance in instances get the value of a property
WString strVal;
ECObjectsStatus status = dgnECInstance->GetValueAsString(strVal, m_propertyName, false, 1);

//API's to read relationship between ECInstances
//Create QueryRelatedClassSpecifier to specify relationship class
ECRelationshipClassP ecWidgetHasGadgetClass;
QueryRelatedClassSpecifierPtr relatedClassSpecifier = QueryRelatedClassSpecifier::Create(*ecWidgetHasGadgetClass, ecGadgetClass, STRENGTHDIRECTION_Forward, true, true);
//ECRelatedInstanceDirection used in QueryRelatedClassSpecifier to describe the direction of a related instance
//STRENGTHDIRECTION_Forward specifies related instance is the target in the relationship instance
DgnECInstanceIterable relatedInstances = dgnECManager.FindRelatedInstances(*instance, *relatedClassSpecifier, DgnECInstanceCreateContext());
//instance is the result of FindInstances as explain in APIs to read ECInstances
//DgnECInstanceCreateContext in FindRelatedInstances is used to define the set of options and the properties to select when querying for DgnECInstances 
//Write related instances to xml file
InstanceWriteStatus status = relatedInstance->WriteToXmlFile(relationPath.c_str(), true, true);
//relationPath is a path of output xml file

  • Managed API to Read EC instances and relationships

//API's to read ECInstances
//Construct an ECQuery to search for instances of a ECClass
ECQuery readWidget = new ECQuery(ecSimpleSchema.GetClass(schema_widget));
readWidget.SelectClause.SelectAllProperties = true;
//Create a scope which finds instances accessible through a dgn file
FindInstancesScope scope = FindInstancesScope.CreateScope(activeDgnModel.GetDgnFile(), new FindInstancesScopeOption(DgnECHostType.Element));
//Find DgnElementECInstances in a dgn file using the supplied scope and query
DgnECInstanceCollection instanceCollection = dgnECManager.FindInstances(scope, readWidget);
//Get the value of property for each foundInstance in instanceCollection 
IDgnECInstance queriedLevelInstance = null;
queriedLevelInstance = foundInstance as IDgnECInstance;
queriedLevelInstance[property_Name].StringValue;

//API's to read relationship between ECInstances
//Create query and scope to get the widget class and its relationship with gadget class
ECQuery widgetHasGadgetQuery = new ECQuery(ecSimpleSchema.GetClass(schema_widget));
widgetHasGadgetQuery.SelectClause.SelectAllProperties = true;
QueryRelatedClassSpecifier queryRelatedClassSpecifier = new QueryRelatedClassSpecifier(widgetRelationshipClass, false, RelatedInstanceDirection.Backward, ecGadgetClass, false);
RelatedInstanceSelectCriteria relatedSelectCriterion = new RelatedInstanceSelectCriteria(queryRelatedClassSpecifier, true);
widgetHasGadgetQuery.SelectClause.SelectedRelatedInstances.Add(relatedSelectCriterion);
//Create a scope which finds instances hosted on element in DgnModel
FindInstancesScope scope = FindInstancesScope.CreateScope(activeDgnModel, new FindInstancesScopeOption(DgnECHostType.Element, true));
DgnECInstanceCollection instanceCollection = dgnECManager.FindInstances(scope, widgetHasGadgetQuery);
//foundInstance is a IDgnECInstance in instanceCollection 
IECRelationshipInstance relatedECInstance in foundInstance.GetRelationshipInstances();
IECInstance sourceInstance = relatedECInstance.Source;
IECInstance targetInstance = relatedECInstance.Target;
//Write instances to xml file
//relationPath is a path of output xml file
XmlTextWriter xmlTextWriter = new XmlTextWriter(relationPath, null); 
ECInstanceXmlWriter ecXmlWriter = new ECInstanceXmlWriter();
ecXmlWriter.Serialize(xmlTextWriter, sourceInstance);
ecXmlWriter.Serialize(xmlTextWriter, targetInstance);
ecXmlWriter.Serialize(xmlTextWriter, relatedECInstance);

API’s to Update EC instances and relationships

Following are the APIs used to Update EC instances and relationship between EC instances:

  • Native API to Update EC instances and relationships

//To update the instances update their property value
static DgnElementECInstancePtr s_gadgetInstance
s_gadgetInstance->SetValueAsString(dgnECNativeCrudExample.m_propertyName, L"Sample App Gadget name changed",false,0);
s_gadgetInstance->WriteChanges();

//To update the relationship call Delete and Create APIs
dgnECNativeCrudExample.DeleteWidgetGadgetRelationship(true);
dgnECNativeCrudExample.CreatingWidgetGadgetRelationship(true);

  • Managed API to  Update EC instances and relationships

//To update the instance update their property values.
static IDgnECInstance gadgetInstance
gadgetInstance.SetAsString(property_Name, "Sample App Gadget name changed"); 
gadgetInstance.WriteChanges();

//To update the relationship call Delete and Create APIs
DeleteWidgetGadgetRelationship("Delete"); 
CreatingWidgetGadgetRelationship("Update");

API’s to Delete EC instances and relationships

Following are the APIs used to Delete EC instances and relationship between EC instances:

  • Native API to Delete EC instances and relationships

//Delete ECInstance
static DgnElementECInstancePtr s_widgetInstance;
DgnECInstanceStatus status = s_widgetInstance ->Delete();

//Delete Relationships
ECRelationshipClassP ecWidgetHasGadgetClass = dynamic_cast<ECRelationshipClassP>(s_ecSchema-> GetClassP(dgnECNativeCrudExample.m_relationship));
BentleyStatus status = DgnECManager::GetManager().DeleteRelationship(*s_widgetInstance, *s_gadgetInstance, *ecWidgetHasGadgetClass);

  • Managed API to Delete EC instances and relationships

//Delete ECInstance
static IDgnECInstance gadgetInstance;
gadgetInstance.Delete();

//Delete relationship
static IECRelationshipInstance relationshipInstance;
DgnECManager.DeleteRelationship(relationshipInstance, activeDgnModel);

 

To refer SDK samples for DgnEC CRUD operations follow below paths 

For Managed : ..\Bentley\MicroStationCONNECTSDK\examples\DgnEC\DgnECManagedCrudExample

For Native : Path should be available in next update.