public KnowledgeGraphPropertyInfo GetPropertyNameInfo()
Public Function GetPropertyNameInfo() As KnowledgeGraphPropertyInfo
public KnowledgeGraphPropertyInfo GetPropertyNameInfo()
Public Function GetPropertyNameInfo() As KnowledgeGraphPropertyInfo
Exception | Description |
---|---|
ArcGIS.Core.CalledOnWrongThreadException | This method or property must be called within the lambda passed to QueuedTask.Run. |
internal void KnowledgeGraphProvenance(KnowledgeGraph kg) { // use the KnowledgeGraphPropertyInfo var propInfo = kg.GetPropertyNameInfo(); var supportsProvenance = propInfo.SupportsProvenance; var provenanceType = propInfo.ProvenanceTypeName; var provenanceInfo = propInfo.ProvenancePropertyInfo; }
var create_rel = await QueuedTask.Run(() => { //Instantiate an operation for the Create var edit_op = new EditOperation() { Name = "Create a new relationship record", SelectNewFeatures = true }; //Use datasets or feature layer(s) or standalone table(s) //Get a reference to the KnowledgeGraph //var kg = ... ; //We will use a relate called 'HasEmployee' to relate an Organization w/ a Person //Use either tables or map members to get the rows to be related... var org_fc = kg.OpenDataset<FeatureClass>("Organization"); var person_tbl = kg.OpenDataset<Table>("Person"); //Get the relationship dataset //We can use either a table or standalone table var emp_tbl = kg.OpenDataset<Table>("HasEmployee"); //we need the names of the origin and destination relationship properties var kg_prop_info = kg.GetPropertyNameInfo(); //Arbitrarily use the first record from the two entity datasets "to be" related //Entities are always related by Global ID. Origin to Destination specifies the //direction (of the relate). // //Populate the attributes for the relationship var attribs = new Dictionary<string, object>(); using (var rc = org_fc.Search()) { if (rc.MoveNext()) //Use the KnowledgeGraphPropertyInfo to avoid hardcoding... attribs[kg_prop_info.OriginIDPropertyName] = rc.Current.GetGlobalID(); } using (var rc = person_tbl.Search()) { if (rc.MoveNext()) //Use the KnowledgeGraphPropertyInfo to avoid hardcoding... attribs[kg_prop_info.DestinationIDPropertyName] = rc.Current.GetGlobalID(); } //Add any extra attribute information for the relation as needed attribs["StartDate"] = new DateTimeOffset(DateTime.Now); //Add a create for the relationship to the operation edit_op.Create(emp_tbl, attribs); //Do the create return edit_op.Execute(); });
var create_rel1 = await QueuedTask.Run(() => { //This example uses a chained edit operation var edit_op = new EditOperation() { Name = "Create entities and a relationship", SelectNewFeatures = true }; //We are just going to use the GDB objects in this one but //we could equally use feature layers/standalone tables //using Feature Class/Tables (works within Investigation or map) var org_fc = kg.OpenDataset<FeatureClass>("Organization"); var person_tbl = kg.OpenDataset<Table>("Person"); //Relationship table var emp_tbl = kg.OpenDataset<Table>("HasEmployee"); var attribs = new Dictionary<string, object>(); //New Organization attribs["Name"] = "Acme Ltd."; attribs["Description"] = "Specializes in household items"; attribs["SHAPE"] = org_location; //Add it to the operation - we need the rowtoken var rowtoken = edit_op.Create(org_fc, attribs); attribs.Clear();//we are going to re-use the dictionary //New Person attribs["Name"] = "Bob"; attribs["Age"] = "41"; attribs["Skills"] = "Plumbing, Framing, Flooring"; //Add it to the operation var rowtoken2 = edit_op.Create(person_tbl, attribs); attribs.Clear(); //At this point we must execute the create of the entities if (edit_op.Execute()) { //if we are here, the create of the entities was successful //Next, "chain" a second create for the relationship - this ensures that //Both creates (entities _and_ relation) will be -undone- together if needed //....in other words they will behave as if they are a -single- transaction var edit_op_rel = edit_op.CreateChainedOperation(); //we need the names of the origin and destination relation properties var kg_prop_info = kg.GetPropertyNameInfo(); //use the row tokens we held on to from the entity creates attribs[kg_prop_info.OriginIDPropertyName] = rowtoken.GlobalID; attribs[kg_prop_info.DestinationIDPropertyName] = rowtoken2.GlobalID; //Add any extra attribute information for the relation as needed attribs["StartDate"] = new DateTimeOffset(DateTime.Now); //Do the create of the relate edit_op_rel.Create(emp_tbl, attribs); return edit_op_rel.Execute(); } return false;//Create of entities failed });
await QueuedTask.Run(() => { //Instantiate an operation for the Create var edit_op = new EditOperation() { Name = "Create a new provenance record", SelectNewFeatures = true }; //lets get the provenance table (provenance is not added to the //map TOC) var provenance_tbl = kg.OpenDataset<Table>("Provenance"); if (provenance_tbl == null) return; //we will add a row to the provenance for person entity var person_tbl = kg.OpenDataset<Table>("Person"); //Arbitrarily retrieve the first "person" row var instance_id = Guid.Empty; using (var rc = person_tbl.Search()) { if (!rc.MoveNext()) return; instance_id = rc.Current.GetGlobalID();//Get the global id } //Define the provenance attributes - we need the names //of the provenance properties from the KG ProvenancePropertyInfo var kg_prop_info = kg.GetPropertyNameInfo(); var attribs = new Dictionary<string, object>(); var ppi = kg_prop_info.ProvenancePropertyInfo; attribs[ppi.ProvenanceTypeNamePropertyName] = person_tbl.GetDefinition().GetName();//entity type name attribs[ppi.ProvenanceFieldNamePropertyName] = "name";//Must be a property/field on the entity attribs[ppi.ProvenanceSourceNamePropertyName] = "Annual Review 2024";//can be anything - can be null //note: Source type is controlled by the CodedValueDomain "esri__provenanceSourceType" attribs[ppi.ProvenanceSourceTypePropertyName] = "Document";//one of ["Document", "String", "URL"]. attribs[ppi.ProvenanceSourcePropertyName] = "HR records";//can be anything, not null attribs[ppi.ProvenanceCommentPropertyName] = "Rock star";//can be anything - can be null //Add in the id of the provenance owner - our "person" in this case attribs[ppi.ProvenanceInstanceIDPropertyName] = instance_id; //Specify any additional custom attributes added to the provenance //schema by the user as needed.... //attribs["custom_attrib"] = "Foo"; //attribs["custom_attrib2"] = "Bar"; //Create the provenance row edit_op.Create(provenance_tbl, attribs); if (edit_op.Execute()) { //TODO: Operation succeeded } });
internal static string GetDocumentTypeName(KnowledgeGraphDataModel kg_dm) { var entity_types = kg_dm.GetEntityTypes(); foreach (var entity_type in entity_types) { var role = entity_type.Value.GetRole(); if (role == KnowledgeGraphNamedObjectTypeRole.Document) return entity_type.Value.GetName(); } return ""; } internal static string GetHasDocumentTypeName(KnowledgeGraphDataModel kg_dm) { var rel_types = kg_dm.GetRelationshipTypes(); foreach (var rel_type in rel_types) { var role = rel_type.Value.GetRole(); if (role == KnowledgeGraphNamedObjectTypeRole.Document) return rel_type.Value.GetName(); } return ""; } internal async void AddDocumentRecord() { await QueuedTask.Run(() => { using (var kg = GetKnowledgeGraph()) { var edit_op = new EditOperation() { Name = "Create Document Example", SelectNewFeatures = true }; var doc_entity_name = GetDocumentTypeName(kg.GetDataModel()); if (string.IsNullOrEmpty(doc_entity_name)) return false; var hasdoc_rel_name = GetHasDocumentTypeName(kg.GetDataModel()); if (string.IsNullOrEmpty(hasdoc_rel_name)) return false; //Document can also be FeatureClass var doc_tbl = kg.OpenDataset<Table>(doc_entity_name); var doc_rel_tbl = kg.OpenDataset<Table>(hasdoc_rel_name); //This is the document to be added...file, image, resource, etc. var url = @"E:\Data\Temp\HelloWorld.txt"; var text = System.IO.File.ReadAllText(url); //Set document properties var attribs = new Dictionary<string, object>(); attribs["contentType"] = @"text/plain"; attribs["name"] = System.IO.Path.GetFileName(url); attribs["url"] = url; //Add geometry if relevant //attribs["Shape"] = doc_location; //optional attribs["fileExtension"] = System.IO.Path.GetExtension(url); attribs["text"] = System.IO.File.ReadAllText(url); //optional and arbitrary - your choice attribs["title"] = System.IO.Path.GetFileNameWithoutExtension(url); attribs["keywords"] = @"text,file,example"; attribs["metadata"] = ""; //Specify any additional custom attributes added to the document //schema by the user as needed.... //attribs["custom_attrib"] = "Foo"; //attribs["custom_attrib2"] = "Bar"; //Get the entity whose document this is... var org_fc = kg.OpenDataset<FeatureClass>("Organization"); var qf = new QueryFilter() { WhereClause = "name = 'Acme'", SubFields = "*" }; var origin_org_id = Guid.Empty; using (var rc = org_fc.Search(qf)) { if (!rc.MoveNext()) return false; origin_org_id = rc.Current.GetGlobalID();//For the relate } //Create the document row/feature var rowtoken = edit_op.Create(doc_tbl, attribs); if (edit_op.Execute()) { //Create the relationship row attribs.Clear(); //we need the names of the origin and destination relation properties var kg_prop_info = kg.GetPropertyNameInfo(); //Specify the origin entity (i.e. the document 'owner') and //the document being related to (i.e. the document 'itself') attribs[kg_prop_info.OriginIDPropertyName] = origin_org_id;//entity attribs[kg_prop_info.DestinationIDPropertyName] = rowtoken.GlobalID;//document //Specify any custom attributes added to the has document //schema by the user as needed.... //attribs["custom_attrib"] = "Foo"; //attribs["custom_attrib2"] = "Bar"; //"Chain" a second create for the relationship - this ensures that //Both creates (doc _and_ "has doc" relation) will be -undone- together if needed //....in other words they will behave as if they are a -single- transaction var edit_op_rel = edit_op.CreateChainedOperation(); edit_op_rel.Create(doc_rel_tbl, attribs); return edit_op_rel.Execute(); } } return false; }); }
await QueuedTask.Run(() => { var edit_op = new EditOperation() { Name = "Modify an Entity and Relationship record", SelectModifiedFeatures = true }; //We are going to use mapmembers in this example //we could equally use feature classes/tables var kg_layer = mv.Map.GetLayersAsFlattenedList()? .OfType<ArcGIS.Desktop.Mapping.KnowledgeGraphLayer>().First(); //Entity var org_fl = kg_layer.GetLayersAsFlattenedList().OfType<FeatureLayer>() .First(child_layer => child_layer.Name == "Organization"); //and/or Relationship var rel_stbl = kg_layer.GetStandaloneTablesAsFlattenedList() .First(child_layer => child_layer.Name == "HasEmployee"); //Get the entity feature to modify long org_oid = -1; var org_gid = Guid.Empty; var qf = new QueryFilter() { WhereClause = "name = 'Acme'", SubFields = "*" }; using (var rc = org_fl.Search(qf)) { if (!rc.MoveNext()) return; org_oid = rc.Current.GetObjectID(); org_gid = rc.Current.GetGlobalID(); } if (org_oid == -1) return; //nothing to modify var attribs = new Dictionary<string, object>(); //Specify attributes to be updated attribs["Name"] = "Acme Ltd."; attribs["Description"] = "Specializes in household items"; attribs["SHAPE"] = org_updated_location; //Add to the edit operation edit_op.Modify(org_fl, org_oid, attribs); //Get the relationship record (if a relate is being updated) //we need the name of the origin id property var kg_prop_info = kg.GetPropertyNameInfo(); var sql = $"{kg_prop_info.OriginIDPropertyName} = "; sql += "'" + org_gid.ToString("B").ToUpper() + "'"; qf = new QueryFilter() { WhereClause = sql, SubFields = "*" }; long rel_oid = -1; using (var rc = rel_stbl.Search(qf)) { if (!rc.MoveNext()) return; rel_oid = rc.Current.GetObjectID(); } if (rel_oid > -1) { //add the relate row updates to the edit operation attribs.Clear();//we are going to re-use the dictionary attribs["StartDate"] = new DateTimeOffset(DateTime.Now); attribs["custom_attrib"] = "Foo"; attribs["custom_attrib2"] = "Bar"; //Add to the edit operation edit_op.Modify(rel_stbl, rel_oid, attribs); } //do the update(s) if (edit_op.Execute()) { //TODO: Operation succeeded } });
Target Platforms: Windows 11, Windows 10