Public Function GetPropertyNameInfo() As KnowledgeGraphPropertyInfo
public KnowledgeGraphPropertyInfo GetPropertyNameInfo()
Public Function GetPropertyNameInfo() As KnowledgeGraphPropertyInfo
public KnowledgeGraphPropertyInfo GetPropertyNameInfo()
| Exception | Description |
|---|---|
| ArcGIS.Core.CalledOnWrongThreadException | This method or property must be called within the lambda passed to QueuedTask.Run. |
{
await QueuedTask.Run(() =>
{
//Create a connection properties
var kg_props =
new KnowledgeGraphConnectionProperties(new Uri(url));
using (var kg = new KnowledgeGraph(kg_props))
{
// use the KnowledgeGraphPropertyInfo
var propInfo = kg.GetPropertyNameInfo();
var supportsProvenance = propInfo.SupportsProvenance;
var provenanceType = propInfo.ProvenanceTypeName;
var provenanceInfo = propInfo.ProvenancePropertyInfo;
}
});
}
{
await QueuedTask.Run(() =>
{
//Create a connection properties
var kg_props =
new KnowledgeGraphConnectionProperties(new Uri(url));
using (var kg = new KnowledgeGraph(kg_props))
{
// use the KnowledgeGraphPropertyInfo
var propInfo = kg.GetPropertyNameInfo();
var supportsDocs = propInfo.SupportsDocuments;
var documentType = propInfo.DocumentTypeName;
var hasDocumentType = propInfo.HasDocumentTypeName; // available at Pro 3.6 only
var documentInfo = propInfo.DocumentPropertyInfo;
}
});
}
{
var mv = MapView.Active;
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"] = mv.Extent.Center;//whatever is its 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
}
});
}
{
await QueuedTask.Run(() =>
{
// check if provenance supported
var propInfo = kg.GetPropertyNameInfo();
if (!propInfo.SupportsProvenance)
return;
//Instantiate an operation for the Create
var edit_op = new EditOperation()
{
Name = "Create a new provenance record",
SelectNewFeatures = true
};
var provName = propInfo.ProvenanceTypeName;
//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
}
var originHandle = new RowHandle(person_tbl, instance_id);
var pd = new KnowledgeGraphProvenanceDescription(
originHandle, "name", KnowledgeGraphSourceType.Document,
"Annual Review 2024", "HR records", "Rock star");
//Create the provenance row
edit_op.Create(pd);
if (edit_op.Execute())
{
//TODO: Operation succeeded
}
});
}
{
var ok = await QueuedTask.Run(() =>
{
using (var kg_for_doc = kgLayer.GetDatastore())
{
var edit_op = new EditOperation()
{
Name = "Create Document Example",
SelectNewFeatures = true
};
var doc_entity_name = GetDocumentTypeName(kg_for_doc.GetDataModel());
if (string.IsNullOrEmpty(doc_entity_name))
return false;
var hasdoc_rel_name = GetHasDocumentTypeName(kg_for_doc.GetDataModel());
if (string.IsNullOrEmpty(hasdoc_rel_name))
return false;
//Document can also be FeatureClass
var doc_tbl = kg_for_doc.OpenDataset<Table>(doc_entity_name);
var doc_rel_tbl = kg_for_doc.OpenDataset<Table>(hasdoc_rel_name);
//This is the document to be added...file, image, resource, etc.
var doc_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"] = doc_url;
//Add geometry if relevant
//attribs["Shape"] = doc_location;
//optional
attribs["fileExtension"] = System.IO.Path.GetExtension(doc_url);
attribs["text"] = System.IO.File.ReadAllText(doc_url);
//optional and arbitrary - your choice
attribs["title"] = System.IO.Path.GetFileNameWithoutExtension(doc_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_for_doc.OpenDataset<FeatureClass>("Organization");
var qf = new ArcGIS.Core.Data.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_for_doc.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;
}
});
}
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 "";
}
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 "";
}
{
await QueuedTask.Run(() =>
{
using (var kg_for_doc = kgLayer.GetDatastore())
{
var propInfo = kg_for_doc.GetPropertyNameInfo();
if (!propInfo.SupportsDocuments)
return false;
var edit_op = new EditOperation()
{
Name = "Create Document Example",
SelectNewFeatures = true
};
var doc_entity_name = propInfo.DocumentTypeName;
var hasdoc_rel_name = GetHasDocumentTypeName(kg.GetDataModel());
//Document can also be FeatureClass
var doc_tbl = kg_for_doc.OpenDataset<Table>(doc_entity_name);
var doc_rel_tbl = kg_for_doc.OpenDataset<Table>(hasdoc_rel_name);
//This is the document to be added...file, image, resource, etc.
var doc_url = @"E:\Data\Temp\HelloWorld.txt";
// create the KnowledgeGraphDocumentDescription
var kgDocDesc = new KnowledgeGraphDocumentDescription(doc_url);
// if there is a geometry use the following ctor
// var kgDocDesc = new KnowledgeGraphDocumentDescription(doc_url, doc_location);
// if you have additional custom attributes
//var customDocAtts = new Dictionary<string, object>();
//customDocAtts.Add("custom_attrib", "Foo");
//customDocAtts.Add("custom_attrib2", "Bar");
//var kgDocDesc = new KnowledgeGraphDocumentDescription(url, null, customDocAtts);
// add additional properties if required
kgDocDesc.Keywords = @"text,file,example";
// The Create method will auto-populate the Url, Name, FileExtension and contentType fields of the document row
// from the path supplied.
var rowToken = edit_op.Create(doc_tbl, kgDocDesc);
//Get the entity whose document this is...
var org_fc = kg_for_doc.OpenDataset<FeatureClass>("Organization");
var qf = new ArcGIS.Core.Data.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
}
// set up the row handles
var originHandle = new RowHandle(org_fc, origin_org_id); // entity
var destinationHandle = new RowHandle(rowToken); // document
// create the KnowledgeGraphRelationshipDescription
var rd = new KnowledgeGraphRelationshipDescription(originHandle, destinationHandle);
// if you have additional custom attributes for the "HasDocument" relationship
//var customHasDocAtts = new Dictionary<string, object>();
//customHasDocAtts.Add("custom_attrib", "Foo");
//customHasDocAtts.Add("custom_attrib2", "Bar");
//var rd = new KnowledgeGraphRelationshipDescription(originHandle, destinationHandle, customHasDocAtts);
// create the relate record using the same edit operation
edit_op.Create(doc_rel_tbl, rd);
//Call execute to create all the entities and relationship rows _together_
return edit_op.Execute();
}
});
}
{
var mv = MapView.Active;
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 ArcGIS.Core.Data.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"] = mv.Extent.Center;
//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 ArcGIS.Core.Data.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
}
});
}
{
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();
});
}
Target Platforms: Windows 11 Home, Pro, Enterprise (64 bit)