private static void InvokeConnectEntitiesCallback( IEntitySetData source, IEntitySetData target, RelationshipType relationship, RelationshipSide sourceSide, HashSet <AssociationInstance> processedAssociations, ConnectEntitiesCallback connectEntities) { if (connectEntities != null && processedAssociations.Add(new AssociationInstance(source, target, relationship.AssociationType.Name, sourceSide.FromRoleName))) { connectEntities(source, target, relationship.AssociationType.Name, sourceSide.FromRoleName); } }
/// <summary> /// Creates a set of objects based on the specified <paramref name="root"/> entity instance /// and only its required relationships. /// </summary> /// <param name="entitySetName">The entity set name for the root entity.</param> /// <param name="root">The root entity around which the graph is based.</param> /// <param name="entityCreated">A callback function invoked every time a new entity instance is created and its properties are initialized.</param> /// <param name="connectEntities">A callback used to connect two objects together. Examples of actions include setting navigation properties, /// synchronizing FKs to PK values, and/or using the IRelatedEnd or SetLink APIs. The first two parameters are the objects that need to /// be connected, and the third is the <see cref="RelationshipSide"/> describing the side of the relationship which the first object participates /// in.</param> /// <returns>A list of <see cref="IEntitySetData"/> representing all objects in the graph used to satisfy the required relationships. /// The first object in the list is always the <paramref name="root"/>.</returns> public IList <IEntitySetData> CreateGraphWithRequiredRelationships( string entitySetName, object root, Action <IEntitySetData> entityCreated, ConnectEntitiesCallback connectEntities) { ExceptionUtilities.CheckArgumentNotNull(root, "root"); ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(entitySetName, "entitySetName"); ExceptionUtilities.CheckObjectNotNull( this.ObjectServices, "An {0} instance is required to create graphs. Populate the ObjectServices property.", typeof(IEntityModelObjectServices).Name, ExpressionUtilities.NameOf(() => this.ObjectServices)); var dataPopulationDriver = this.CreateDataPopulationDriver(); var rootEntitySet = this.entityContainer.EntitySets.SingleOrDefault(es => es.ContainerQualifiedName == entitySetName); var rootEntityType = this.entityContainer.Model.EntityTypes.SingleOrDefault(et => et.Name == root.GetType().Name); ExceptionUtilities.CheckObjectNotNull(rootEntitySet, "Could not locate entity set '{0}' in the model.", entitySetName); ExceptionUtilities.CheckObjectNotNull(rootEntityType, "Could not locate entity type '{0}' in the model.", root.GetType().FullName); var rootKey = dataPopulationDriver.Seed(rootEntitySet, rootEntityType, this.ObjectServices.GetPropertiesValues(root, rootEntityType)); var data = this.CreateEntityContainerData(dataPopulationDriver); var graph = new List <IEntitySetData>(); var rootData = this.CreateEntitySetObjectData(root, entitySetName); graph.Add(rootData); if (data != null) { var processedEntities = new Dictionary <EntityKey, IEntitySetData>(); processedEntities.Add(new EntityKey(entitySetName, rootKey), rootData); this.CreateGraphCore( graph, rootData, rootEntitySet, rootEntityType, rootKey, data, processedEntities, new HashSet <AssociationInstance>(), entityCreated, connectEntities); } return(graph); }
/// <summary> /// Examines the required relationships from <paramref name="source"/> and then populates them in <paramref name="graph"/>. /// </summary> /// <param name="graph">The <see cref="List{IEntitySetData}"/> to which to add the new instance.</param> /// <param name="source">The entity from which to find required relationships and populate them.</param> /// <param name="sourceEntitySet">The <see cref="EntitySet"/> in which <paramref name="source"/> resides.</param> /// <param name="sourceEntityType">The <see cref="EntityType"/> of which the <paramref name="source"/> is an instance.</param> /// <param name="sourceKey">The <see cref="EntityDataKey"/> of the <paramref name="source"/> instance.</param> /// <param name="data"><see cref="EntityContainerData"/> that contains the structural data from which to create objects.</param> /// <param name="processedEntities">The entity instances which have been translated from structural data into objects.</param> /// <param name="processedAssociations">The association instances which have been translated from structural data into calls to <paramref name="connectEntities"/>.</param> /// <param name="entityCreated">A callback function invoked every time a new entity instance is created and its properties are initialized.</param> /// <param name="connectEntities">A callback used to connect two objects together. Examples of actions include setting navigation properties, /// synchronizing FKs to PK values, and/or using the IRelatedEnd or SetLink APIs. The first two parameters are the objects that need to /// be connected, and the third is the <see cref="RelationshipSide"/> describing the side of the relationship which the first object participates /// in.</param> private void CreateGraphCore( List <IEntitySetData> graph, IEntitySetData source, EntitySet sourceEntitySet, EntityType sourceEntityType, EntityDataKey sourceKey, EntityContainerData data, Dictionary <EntityKey, IEntitySetData> processedEntities, HashSet <AssociationInstance> processedAssociations, Action <IEntitySetData> entityCreated, ConnectEntitiesCallback connectEntities) { var requiredRelationships = from r in sourceEntitySet.Container.RelationshipTypes() let side = r.Sides.FirstOrDefault(e => sourceEntityType.IsKindOf(e.FromEntityType) && sourceEntitySet == e.FromEntitySet && e.ToMultiplicity == EndMultiplicity.One) where side != null select new { Relationship = r, SourceSide = side }; foreach (var r in requiredRelationships) { var relationship = r.Relationship; var sourceSide = r.SourceSide; var associationRow = data.GetAssociationSetData(relationship.AssociationSet.Name).Rows .Single(row => row.GetRoleKey(sourceSide.FromRoleName).Equals(sourceKey)); var targetKey = associationRow.GetRoleKey(sourceSide.ToRoleName); var targetEntitySet = sourceSide.ToEntitySet; var targetEntityKey = new EntityKey(targetEntitySet.ContainerQualifiedName, targetKey); IEntitySetData targetEntity; if (!processedEntities.TryGetValue(targetEntityKey, out targetEntity)) { var targetRow = data.GetEntitySetData(targetEntitySet.Name).Rows.Single(row => row.Key.Equals(targetKey)); targetEntity = this.CreateObjectFromRow(targetRow); if (entityCreated != null) { entityCreated(targetEntity); } graph.Add(targetEntity); processedEntities.Add(targetEntityKey, targetEntity); InvokeConnectEntitiesCallback(source, targetEntity, relationship, sourceSide, processedAssociations, connectEntities); this.CreateGraphCore( graph, targetEntity, targetEntitySet, targetRow.EntityType, targetKey, data, processedEntities, processedAssociations, entityCreated, connectEntities); } else { InvokeConnectEntitiesCallback(source, targetEntity, relationship, sourceSide, processedAssociations, connectEntities); } } }