internal override void RetrieveReferentialConstraintProperties( Dictionary <string, KeyValuePair <object, IntBox> > properties, HashSet <object> visited) { if (this._wrappedCachedValue.Entity == null) { return; } foreach (ReferentialConstraint referentialConstraint in ((AssociationType)this.RelationMetadata).ReferentialConstraints) { if (referentialConstraint.ToRole == this.FromEndMember) { if (visited.Contains((object)this._wrappedCachedValue)) { throw new InvalidOperationException(Strings.RelationshipManager_CircularRelationshipsWithReferentialConstraints); } visited.Add((object)this._wrappedCachedValue); Dictionary <string, KeyValuePair <object, IntBox> > properties1; this._wrappedCachedValue.RelationshipManager.RetrieveReferentialConstraintProperties(out properties1, visited, true); for (int index = 0; index < referentialConstraint.FromProperties.Count; ++index) { EntityEntry.AddOrIncreaseCounter(referentialConstraint, properties, referentialConstraint.ToProperties[index].Name, properties1[referentialConstraint.FromProperties[index].Name].Key); } } } }
// Method used to retrieve properties from principal entities. // NOTE: 'properties' list is modified in this method and may already contains some properties. internal override void RetrieveReferentialConstraintProperties( Dictionary <string, KeyValuePair <object, IntBox> > properties, HashSet <object> visited) { DebugCheck.NotNull(properties); if (_wrappedCachedValue.Entity != null) { // Dictionary< propertyName, <propertyValue, counter>> Dictionary <string, KeyValuePair <object, IntBox> > retrievedProperties; // PERFORMANCE: ReferentialConstraints collection in typical scenario is very small (1-3 elements) foreach (var constraint in ((AssociationType)RelationMetadata).ReferentialConstraints) { if (constraint.ToRole == FromEndMember) { // Detect circular references if (visited.Contains(_wrappedCachedValue)) { throw new InvalidOperationException(Strings.RelationshipManager_CircularRelationshipsWithReferentialConstraints); } visited.Add(_wrappedCachedValue); _wrappedCachedValue.RelationshipManager.RetrieveReferentialConstraintProperties( out retrievedProperties, visited, includeOwnValues: true); Debug.Assert(retrievedProperties != null); Debug.Assert( constraint.FromProperties.Count == constraint.ToProperties.Count, "Referential constraints From/To properties list have different size"); // Following loop rewrites properties from "retrievedProperties" into "properties". // At the same time, property's name is translated from name from principal end into name from dependent end: // Example: Client<C_ID> - Order<O_ID, Client_ID> // Client is principal end, Order is dependent end, Client.C_ID == Order.Client_ID // Input : retrievedProperties = { "C_ID" = 123 } // Output: properties = { "Client_ID" = 123 } // NOTE order of properties in collections constraint.From/ToProperties is important for (var i = 0; i < constraint.FromProperties.Count; ++i) { EntityEntry.AddOrIncreaseCounter( constraint, properties, constraint.ToProperties[i].Name, retrievedProperties[constraint.FromProperties[i].Name].Key); } } } } }