This blog demonstrates how to use DgnEC native and managed API’s for following:
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:
//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);
//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:
//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);
//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:
//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
//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:
//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);
//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:
//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);
//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.
Great examples in two lanaguages!
Question about Paths
// For Native : PowerPlatformSDK\MstnExamples\DgnEC\DgnECNativeCrudExample // For Managed : PowerPlatformSDK\MstnExamples\DgnEC\DgnECManagedCrudExample
Are those your internal paths to MicroStation examples? The path to an installed SDK is more like:
..\MicroStation\SDK\examples
Thanks Jon for noting this. I have corrected paths in blog.
> For Native : Path should be available in next update.
We're two years further on — when is the next update?