internal void UpdateForeignKeyValues(IEntityWrapper dependentEntity, EntityKey principalKey) { ReferentialConstraint referentialConstraint = ((AssociationType)this.RelationMetadata).ReferentialConstraints[0]; ObjectStateManager objectStateManager = this.ObjectContext.ObjectStateManager; objectStateManager.TransactionManager.BeginForeignKeyUpdate(this); try { EntitySet entitySet = ((AssociationSet)this.RelationshipSet).AssociationSetEnds[this.FromEndMember.Name].EntitySet; StateManagerTypeMetadata managerTypeMetadata = objectStateManager.GetOrAddStateManagerTypeMetadata(dependentEntity.IdentityType, entitySet); for (int index = 0; index < referentialConstraint.FromProperties.Count; ++index) { object valueByName = principalKey.FindValueByName(referentialConstraint.FromProperties[index].Name); int olayerMemberName = managerTypeMetadata.GetOrdinalforOLayerMemberName(referentialConstraint.ToProperties[index].Name); object x = managerTypeMetadata.Member(olayerMemberName).GetValue(dependentEntity.Entity); if (!ByValueEqualityComparer.Default.Equals(x, valueByName)) { dependentEntity.SetCurrentValue(dependentEntity.ObjectStateEntry, managerTypeMetadata.Member(olayerMemberName), -1, dependentEntity.Entity, valueByName); } } this.SetCachedForeignKey(principalKey, dependentEntity.ObjectStateEntry); if (this.WrappedOwner.ObjectStateEntry == null) { return; } objectStateManager.ForgetEntryWithConceptualNull(this.WrappedOwner.ObjectStateEntry, false); } finally { objectStateManager.TransactionManager.EndForeignKeyUpdate(); } }
/// <summary> /// Takes key values from the given principal key and transfers them to the foreign key properties /// of the dependant entry. This method requires a context, but does not require that either /// entity or key is in the context. This allows it to work in NoTracking cases where we have the context /// but we're not tracked by that context. /// </summary> /// <param name="dependentEntity">The entity into which foreign key values will be written</param> /// <param name="principalEntity">The key from which key values will be obtained</param> internal void UpdateForeignKeyValues(IEntityWrapper dependentEntity, EntityKey principalKey) { Debug.Assert(dependentEntity.Entity != null, "dependentEntity.Entity == null"); Debug.Assert(principalKey != null, "principalKey == null"); Debug.Assert(!principalKey.IsTemporary, "Cannot update from a temp key"); Debug.Assert(this.IsForeignKey, "cannot update foreign key values if the relationship is not a FK"); ReferentialConstraint constraint = ((AssociationType)this.RelationMetadata).ReferentialConstraints[0]; Debug.Assert(constraint != null, "null constraint"); ObjectStateManager stateManager = ObjectContext.ObjectStateManager; stateManager.TransactionManager.BeginForeignKeyUpdate(this); try { EntitySet dependentEntitySet = ((AssociationSet)RelationshipSet).AssociationSetEnds[FromEndProperty.Name].EntitySet; StateManagerTypeMetadata dependentTypeMetadata = stateManager.GetOrAddStateManagerTypeMetadata(dependentEntity.IdentityType, dependentEntitySet); for (int i = 0; i < constraint.FromProperties.Count; i++) { object value = principalKey.FindValueByName(constraint.FromProperties[i].Name); int dependentOrdinal = dependentTypeMetadata.GetOrdinalforOLayerMemberName(constraint.ToProperties[i].Name); object currentValue = dependentTypeMetadata.Member(dependentOrdinal).GetValue(dependentEntity.Entity); if (!ByValueEqualityComparer.Default.Equals(currentValue, value)) { dependentEntity.SetCurrentValue( dependentEntity.ObjectStateEntry, dependentTypeMetadata.Member(dependentOrdinal), -1, dependentEntity.Entity, value); } } SetCachedForeignKey(principalKey, dependentEntity.ObjectStateEntry); if (WrappedOwner.ObjectStateEntry != null) { stateManager.ForgetEntryWithConceptualNull(WrappedOwner.ObjectStateEntry, resetAllKeys: false); } } finally { stateManager.TransactionManager.EndForeignKeyUpdate(); } }
/// <summary> /// Takes key values from the given principal key and transfers them to the foreign key properties /// of the dependant entry. This method requires a context, but does not require that either /// entity or key is in the context. This allows it to work in NoTracking cases where we have the context /// but we're not tracked by that context. /// </summary> /// <param name="dependentEntity">The entity into which foreign key values will be written</param> /// <param name="principalEntity">The key from which key values will be obtained</param> internal void UpdateForeignKeyValues(IEntityWrapper dependentEntity, EntityKey principalKey) { Debug.Assert(dependentEntity.Entity != null, "dependentEntity.Entity == null"); Debug.Assert(principalKey != null, "principalKey == null"); Debug.Assert(!principalKey.IsTemporary, "Cannot update from a temp key"); Debug.Assert(IsForeignKey, "cannot update foreign key values if the relationship is not a FK"); var constraint = ((AssociationType)RelationMetadata).ReferentialConstraints[0]; Debug.Assert(constraint != null, "null constraint"); var stateManager = ObjectContext.ObjectStateManager; stateManager.TransactionManager.BeginForeignKeyUpdate(this); try { var dependentEntitySet = ((AssociationSet)RelationshipSet).AssociationSetEnds[FromEndMember.Name].EntitySet; var dependentTypeMetadata = stateManager.GetOrAddStateManagerTypeMetadata(dependentEntity.IdentityType, dependentEntitySet); for (var i = 0; i < constraint.FromProperties.Count; i++) { var value = principalKey.FindValueByName(constraint.FromProperties[i].Name); var dependentOrdinal = dependentTypeMetadata.GetOrdinalforOLayerMemberName(constraint.ToProperties[i].Name); var currentValue = dependentTypeMetadata.Member(dependentOrdinal).GetValue(dependentEntity.Entity); if (!ByValueEqualityComparer.Default.Equals(currentValue, value)) { dependentEntity.SetCurrentValue( dependentEntity.ObjectStateEntry, dependentTypeMetadata.Member(dependentOrdinal), -1, dependentEntity.Entity, value); } } SetCachedForeignKey(principalKey, dependentEntity.ObjectStateEntry); if (WrappedOwner.ObjectStateEntry != null) { stateManager.ForgetEntryWithConceptualNull(WrappedOwner.ObjectStateEntry, resetAllKeys: false); } } finally { stateManager.TransactionManager.EndForeignKeyUpdate(); } }
/// <summary> /// Takes key values from the given principal entity and transfers them to the foreign key properties /// of the dependant entry. This method requires a context, but does not require that either /// entity is in the context. This allows it to work in NoTracking cases where we have the context /// but we're not tracked by that context. /// </summary> /// <param name="dependentEntity">The entity into which foreign key values will be written</param> /// <param name="principalEntity">The entity from which key values will be obtained</param> /// <param name="changedFKs">If non-null, then keeps track of FKs that have already been set such that an exception can be thrown if we find conflicting values</param> /// <param name="forceChange">If true, then the property setter is called even if FK values already match, /// which causes the FK properties to be marked as modified.</param> internal void UpdateForeignKeyValues( IEntityWrapper dependentEntity, IEntityWrapper principalEntity, Dictionary<int, object> changedFKs, bool forceChange) { Debug.Assert(dependentEntity.Entity != null, "dependentEntity.Entity == null"); Debug.Assert(principalEntity.Entity != null, "principalEntity.Entity == null"); Debug.Assert(IsForeignKey, "cannot update foreign key values if the relationship is not a FK"); var constraint = ((AssociationType)RelationMetadata).ReferentialConstraints[0]; Debug.Assert(constraint != null, "null constraint"); var isUnchangedDependent = (object)WrappedOwner.EntityKey != null && !WrappedOwner.EntityKey.IsTemporary && IsDependentEndOfReferentialConstraint(checkIdentifying: true); var stateManager = ObjectContext.ObjectStateManager; stateManager.TransactionManager.BeginForeignKeyUpdate(this); try { var principalEntitySet = ((AssociationSet)RelationshipSet).AssociationSetEnds[ToEndMember.Name].EntitySet; var principalTypeMetadata = stateManager.GetOrAddStateManagerTypeMetadata(principalEntity.IdentityType, principalEntitySet); var dependentEntitySet = ((AssociationSet)RelationshipSet).AssociationSetEnds[FromEndMember.Name].EntitySet; var dependentTypeMetadata = stateManager.GetOrAddStateManagerTypeMetadata(dependentEntity.IdentityType, dependentEntitySet); var principalProps = constraint.FromProperties; var numValues = principalProps.Count; string[] keyNames = null; object[] values = null; if (numValues > 1) { keyNames = principalEntitySet.ElementType.KeyMemberNames; values = new object[numValues]; } for (var i = 0; i < numValues; i++) { var principalOrdinal = principalTypeMetadata.GetOrdinalforOLayerMemberName(principalProps[i].Name); var value = principalTypeMetadata.Member(principalOrdinal).GetValue(principalEntity.Entity); var dependentOrdinal = dependentTypeMetadata.GetOrdinalforOLayerMemberName(constraint.ToProperties[i].Name); var valueChanging = !ByValueEqualityComparer.Default.Equals( dependentTypeMetadata.Member(dependentOrdinal).GetValue(dependentEntity.Entity), value); if (forceChange || valueChanging) { if (isUnchangedDependent) { ValidateSettingRIConstraints( principalEntity, settingToNull: value == null, changingForeignKeyValue: valueChanging); } // If we're tracking FK values that have already been set, then compare the value we are about to set // to the value we previously set for this ordinal, if such a value exists. If they don't match then // it means that we got conflicting FK values from two different PKs and we should throw. if (changedFKs != null) { object previouslySetValue; if (changedFKs.TryGetValue(dependentOrdinal, out previouslySetValue)) { if (!ByValueEqualityComparer.Default.Equals(previouslySetValue, value)) { throw new InvalidOperationException(Strings.Update_ReferentialConstraintIntegrityViolation); } } else { changedFKs[dependentOrdinal] = value; } } dependentEntity.SetCurrentValue( dependentEntity.ObjectStateEntry, dependentTypeMetadata.Member(dependentOrdinal), -1, dependentEntity.Entity, value); } if (numValues > 1) { var keyIndex = Array.IndexOf(keyNames, principalProps[i].Name); Debug.Assert(keyIndex >= 0 && keyIndex < numValues, "Could not find constraint prop name in entity set key names"); values[keyIndex] = value; } else { SetCachedForeignKey(new EntityKey(principalEntitySet, value), dependentEntity.ObjectStateEntry); } } if (numValues > 1) { SetCachedForeignKey(new EntityKey(principalEntitySet, values), dependentEntity.ObjectStateEntry); } if (WrappedOwner.ObjectStateEntry != null) { stateManager.ForgetEntryWithConceptualNull(WrappedOwner.ObjectStateEntry, resetAllKeys: false); } } finally { stateManager.TransactionManager.EndForeignKeyUpdate(); } }
/// <summary> /// Takes key values from the given principal entity and transfers them to the foreign key properties /// of the dependant entry. This method requires a context, but does not require that either /// entity is in the context. This allows it to work in NoTracking cases where we have the context /// but we're not tracked by that context. /// </summary> /// <param name="dependentEntity">The entity into which foreign key values will be written</param> /// <param name="principalEntity">The entity from which key values will be obtained</param> /// <param name="changedFKs">If non-null, then keeps track of FKs that have already been set such that an exception can be thrown if we find conflicting values</param> /// <param name="forceChange">If true, then the property setter is called even if FK values already match, /// which causes the FK properties to be marked as modified.</param> internal void UpdateForeignKeyValues(IEntityWrapper dependentEntity, IEntityWrapper principalEntity, Dictionary <int, object> changedFKs, bool forceChange) { Debug.Assert(dependentEntity.Entity != null, "dependentEntity.Entity == null"); Debug.Assert(principalEntity.Entity != null, "principalEntity.Entity == null"); Debug.Assert(this.IsForeignKey, "cannot update foreign key values if the relationship is not a FK"); ReferentialConstraint constraint = ((AssociationType)this.RelationMetadata).ReferentialConstraints[0]; Debug.Assert(constraint != null, "null constraint"); bool isUnchangedDependent = (object)WrappedOwner.EntityKey != null && !WrappedOwner.EntityKey.IsTemporary && IsDependentEndOfReferentialConstraint(checkIdentifying: true); ObjectStateManager stateManager = ObjectContext.ObjectStateManager; stateManager.TransactionManager.BeginForeignKeyUpdate(this); try { EntitySet principalEntitySet = ((AssociationSet)RelationshipSet).AssociationSetEnds[ToEndMember.Name].EntitySet; StateManagerTypeMetadata principalTypeMetadata = stateManager.GetOrAddStateManagerTypeMetadata(principalEntity.IdentityType, principalEntitySet); EntitySet dependentEntitySet = ((AssociationSet)RelationshipSet).AssociationSetEnds[FromEndProperty.Name].EntitySet; StateManagerTypeMetadata dependentTypeMetadata = stateManager.GetOrAddStateManagerTypeMetadata(dependentEntity.IdentityType, dependentEntitySet); var principalProps = constraint.FromProperties; int numValues = principalProps.Count; string[] keyNames = null; object[] values = null; if (numValues > 1) { keyNames = principalEntitySet.ElementType.KeyMemberNames; values = new object[numValues]; } for (int i = 0; i < numValues; i++) { int principalOrdinal = principalTypeMetadata.GetOrdinalforOLayerMemberName(principalProps[i].Name); object value = principalTypeMetadata.Member(principalOrdinal).GetValue(principalEntity.Entity); int dependentOrdinal = dependentTypeMetadata.GetOrdinalforOLayerMemberName(constraint.ToProperties[i].Name); bool valueChanging = !ByValueEqualityComparer.Default.Equals(dependentTypeMetadata.Member(dependentOrdinal).GetValue(dependentEntity.Entity), value); if (forceChange || valueChanging) { if (isUnchangedDependent) { ValidateSettingRIConstraints(principalEntity, settingToNull: value == null, changingForeignKeyValue: valueChanging); } // If we're tracking FK values that have already been set, then compare the value we are about to set // to the value we previously set for this ordinal, if such a value exists. If they don't match then // it means that we got conflicting FK values from two different PKs and we should throw. if (changedFKs != null) { object previouslySetValue; if (changedFKs.TryGetValue(dependentOrdinal, out previouslySetValue)) { if (!ByValueEqualityComparer.Default.Equals(previouslySetValue, value)) { throw new InvalidOperationException(System.Data.Entity.Strings.Update_ReferentialConstraintIntegrityViolation); } } else { changedFKs[dependentOrdinal] = value; } } dependentEntity.SetCurrentValue( dependentEntity.ObjectStateEntry, dependentTypeMetadata.Member(dependentOrdinal), -1, dependentEntity.Entity, value); } if (numValues > 1) { int keyIndex = Array.IndexOf(keyNames, principalProps[i].Name); Debug.Assert(keyIndex >= 0 && keyIndex < numValues, "Could not find constraint prop name in entity set key names"); values[keyIndex] = value; } else { SetCachedForeignKey(new EntityKey(principalEntitySet, value), dependentEntity.ObjectStateEntry); } } if (numValues > 1) { SetCachedForeignKey(new EntityKey(principalEntitySet, values), dependentEntity.ObjectStateEntry); } if (WrappedOwner.ObjectStateEntry != null) { stateManager.ForgetEntryWithConceptualNull(WrappedOwner.ObjectStateEntry, resetAllKeys: false); } } finally { stateManager.TransactionManager.EndForeignKeyUpdate(); } }
internal void UpdateForeignKeyValues( IEntityWrapper dependentEntity, IEntityWrapper principalEntity, Dictionary <int, object> changedFKs, bool forceChange) { ReferentialConstraint referentialConstraint = ((AssociationType)this.RelationMetadata).ReferentialConstraints[0]; bool flag = (object)this.WrappedOwner.EntityKey != null && !this.WrappedOwner.EntityKey.IsTemporary && this.IsDependentEndOfReferentialConstraint(true); ObjectStateManager objectStateManager = this.ObjectContext.ObjectStateManager; objectStateManager.TransactionManager.BeginForeignKeyUpdate(this); try { EntitySet entitySet1 = ((AssociationSet)this.RelationshipSet).AssociationSetEnds[this.ToEndMember.Name].EntitySet; StateManagerTypeMetadata managerTypeMetadata1 = objectStateManager.GetOrAddStateManagerTypeMetadata(principalEntity.IdentityType, entitySet1); EntitySet entitySet2 = ((AssociationSet)this.RelationshipSet).AssociationSetEnds[this.FromEndMember.Name].EntitySet; StateManagerTypeMetadata managerTypeMetadata2 = objectStateManager.GetOrAddStateManagerTypeMetadata(dependentEntity.IdentityType, entitySet2); ReadOnlyMetadataCollection <EdmProperty> fromProperties = referentialConstraint.FromProperties; int count = fromProperties.Count; string[] array = (string[])null; object[] compositeKeyValues = (object[])null; if (count > 1) { array = entitySet1.ElementType.KeyMemberNames; compositeKeyValues = new object[count]; } for (int index1 = 0; index1 < count; ++index1) { int olayerMemberName1 = managerTypeMetadata1.GetOrdinalforOLayerMemberName(fromProperties[index1].Name); object obj = managerTypeMetadata1.Member(olayerMemberName1).GetValue(principalEntity.Entity); int olayerMemberName2 = managerTypeMetadata2.GetOrdinalforOLayerMemberName(referentialConstraint.ToProperties[index1].Name); bool changingForeignKeyValue = !ByValueEqualityComparer.Default.Equals(managerTypeMetadata2.Member(olayerMemberName2).GetValue(dependentEntity.Entity), obj); if (forceChange || changingForeignKeyValue) { if (flag) { this.ValidateSettingRIConstraints(principalEntity, obj == null, changingForeignKeyValue); } if (changedFKs != null) { object x; if (changedFKs.TryGetValue(olayerMemberName2, out x)) { if (!ByValueEqualityComparer.Default.Equals(x, obj)) { throw new InvalidOperationException(Strings.Update_ReferentialConstraintIntegrityViolation); } } else { changedFKs[olayerMemberName2] = obj; } } dependentEntity.SetCurrentValue(dependentEntity.ObjectStateEntry, managerTypeMetadata2.Member(olayerMemberName2), -1, dependentEntity.Entity, obj); } if (count > 1) { int index2 = Array.IndexOf <string>(array, fromProperties[index1].Name); compositeKeyValues[index2] = obj; } else { this.SetCachedForeignKey(obj == null ? (EntityKey)null : new EntityKey((EntitySetBase)entitySet1, obj), dependentEntity.ObjectStateEntry); } } if (count > 1) { this.SetCachedForeignKey(((IEnumerable <object>)compositeKeyValues).Any <object>((Func <object, bool>)(v => v == null)) ? (EntityKey)null : new EntityKey((EntitySetBase)entitySet1, compositeKeyValues), dependentEntity.ObjectStateEntry); } if (this.WrappedOwner.ObjectStateEntry == null) { return; } objectStateManager.ForgetEntryWithConceptualNull(this.WrappedOwner.ObjectStateEntry, false); } finally { objectStateManager.TransactionManager.EndForeignKeyUpdate(); } }