Skip to content

Commit

Permalink
Initial support for m2m reflexive relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
abvogel committed Jun 6, 2019
1 parent 03968a5 commit d26db51
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
Binary file not shown.
24 changes: 21 additions & 3 deletions Microsoft.Xrm.DevOps.Data/Builders/DataBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public void AppendData(String fetchXml)

if (HasManyToManyAttribute(fetchXml))
{
this.AppendM2MData(retrieveMultipleResponse.EntityCollection);
this.AppendM2MData(retrieveMultipleResponse.EntityCollection, GetFirstLinkEntityName(fetchXml));
}
else
{
Expand Down Expand Up @@ -354,7 +354,7 @@ private void RefreshMetadataFromConnection(String logicalName)
{
var retrieveEntityRequest = new RetrieveEntityRequest();
retrieveEntityRequest.LogicalName = logicalName;
retrieveEntityRequest.EntityFilters = EntityFilters.Attributes;
retrieveEntityRequest.EntityFilters = EntityFilters.All;
RetrieveEntityResponse RetrieveEntityResponse = (RetrieveEntityResponse)Service.Execute(retrieveEntityRequest);
this._Entities[logicalName].Metadata = RetrieveEntityResponse.EntityMetadata;
this._Entities[logicalName].FetchedAllMetadata = true;
Expand All @@ -366,13 +366,18 @@ private void AddMetadataFromSchema(SchemaXml.Entity schemaXML)
this._Entities[schemaXML.Name].Metadata = Builders.XmlImporter.GenerateAdditionalMetadata(this._Entities[schemaXML.Name].Metadata, schemaXML);
}

private void AppendM2MData(EntityCollection queryResponse)
private void AppendM2MData(EntityCollection queryResponse, String FirstLinkEntityName)
{
var SourceEntity = queryResponse.EntityName;

Dictionary<Guid, List<Guid>> relationshipPairs = new Dictionary<Guid, List<Guid>>();
String relationshipName = queryResponse.Entities[0].Attributes.Where(x => x.Value is AliasedValue).Select(x => ((AliasedValue)x.Value).EntityLogicalName).First();

if (RelationshipIsReflexive(queryResponse.EntityName, relationshipName))
{
relationshipName = FirstLinkEntityName;
}

foreach (var record in queryResponse.Entities)
{
Guid relatedId = ((Guid)record.Attributes.Where(x => x.Value is AliasedValue).Select(x => ((AliasedValue)x.Value).Value).First());
Expand All @@ -393,6 +398,11 @@ private void AppendM2MData(EntityCollection queryResponse)
this._Entities[SourceEntity].AppendM2MDataToEntity(relationshipName, relationshipPairs);
}

private bool RelationshipIsReflexive(string entityName, string relationshipName)
{
return entityName.Equals(relationshipName);
}

private bool HasManyToManyAttribute(string fetchXml)
{
XmlDocument xml = new XmlDocument();
Expand All @@ -406,6 +416,14 @@ private bool HasManyToManyAttribute(string fetchXml)
return false;
}

private string GetFirstLinkEntityName(string fetchXml)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(fetchXml);

return xml.SelectSingleNode("fetch/entity/link-entity[@intersect='true']/@name").Value;
}

private void FinalizeEntity(string logicalName)
{
// Always include the guid as a field if it is set for the entity.
Expand Down
8 changes: 7 additions & 1 deletion Microsoft.Xrm.DevOps.Data/Builders/XmlDataBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,17 @@ private static DataXml.Entity GenerateEntityNode(String logicalName, BuilderEnti

foreach (KeyValuePair<Guid, List<Guid>> relationshipPair in builderEntityMetadata.RelatedEntities[relationshipName])
{
string targetPrimaryKey = relationshipMetadata.Entity2IntersectAttribute;
if (relationshipMetadata.Entity1LogicalName == relationshipMetadata.Entity2LogicalName)
{
targetPrimaryKey = relationshipMetadata.Entity2IntersectAttribute.Substring(0, relationshipMetadata.Entity2IntersectAttribute.Length - 3);
}

var relationship = new M2mrelationship()
{
Sourceid = relationshipPair.Key.ToString(),
Targetentityname = relationshipMetadata.Entity2LogicalName,
Targetentitynameidfield = relationshipMetadata.Entity2IntersectAttribute,
Targetentitynameidfield = targetPrimaryKey,
M2mrelationshipname = relationshipMetadata.IntersectEntityName,
Targetids = new Targetids()
{
Expand Down
9 changes: 8 additions & 1 deletion Microsoft.Xrm.DevOps.Data/Builders/XmlSchemaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,22 @@ private static Entity GenerateEntityNode(string logicalName, BuilderEntityMetada
{
var relationshipMetadata = builderEntityMetadata.Metadata.ManyToManyRelationships.Where(x => x.IntersectEntityName == relationshipname).First();

string targetPrimaryKey = relationshipMetadata.Entity2IntersectAttribute;
if (relationshipMetadata.Entity1LogicalName == relationshipMetadata.Entity2LogicalName)
{
targetPrimaryKey = relationshipMetadata.Entity2IntersectAttribute.Substring(0, relationshipMetadata.Entity2IntersectAttribute.Length - 3);
}

entityNode.Relationships.Relationship.Add(new SchemaXml.Relationship()
{
Name = relationshipname,
ManyToMany = "true",
Isreflexive = (relationshipMetadata.Entity1LogicalName == relationshipMetadata.Entity2LogicalName).ToString().ToLower(),
RelatedEntityName = relationshipMetadata.IntersectEntityName,
M2mTargetEntity = relationshipMetadata.Entity2LogicalName,
M2mTargetEntityPrimaryKey = relationshipMetadata.Entity2IntersectAttribute
M2mTargetEntityPrimaryKey = targetPrimaryKey
});

}
}

Expand Down

0 comments on commit d26db51

Please sign in to comment.