コード例 #1
0
        private void IncludeEntityKey(bool doAttach)
        {
            ObjectStateManager objectStateManager = this.ObjectContext.ObjectStateManager;
            bool        flag1       = false;
            bool        flag2       = false;
            EntityEntry entityEntry = objectStateManager.FindEntityEntry(this.DetachedEntityKey);

            if (entityEntry == null)
            {
                flag2 = true;
                flag1 = true;
            }
            else if (entityEntry.IsKeyEntry)
            {
                if (this.FromEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)
                {
                    foreach (RelationshipEntry relationshipEntry in this.ObjectContext.ObjectStateManager.FindRelationshipsByKey(this.DetachedEntityKey))
                    {
                        if (relationshipEntry.IsSameAssociationSetAndRole((AssociationSet)this.RelationshipSet, (AssociationEndMember)this.ToEndMember, this.DetachedEntityKey) && relationshipEntry.State != EntityState.Deleted)
                        {
                            throw new InvalidOperationException(Strings.ObjectStateManager_EntityConflictsWithKeyEntry);
                        }
                    }
                }
                flag1 = true;
            }
            else
            {
                IEntityWrapper wrappedEntity = entityEntry.WrappedEntity;
                if (entityEntry.State == EntityState.Deleted)
                {
                    throw new InvalidOperationException(Strings.RelatedEnd_UnableToAddRelationshipWithDeletedEntity);
                }
                RelatedEnd relatedEndInternal = wrappedEntity.RelationshipManager.GetRelatedEndInternal(this.RelationshipName, this.RelationshipNavigation.From);
                if (this.FromEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many && !relatedEndInternal.IsEmpty())
                {
                    throw new InvalidOperationException(Strings.ObjectStateManager_EntityConflictsWithKeyEntry);
                }
                this.Add(wrappedEntity, true, doAttach, false, true, true);
                objectStateManager.TransactionManager.PopulatedEntityReferences.Add((EntityReference)this);
            }
            if (!flag1 || this.IsForeignKey)
            {
                return;
            }
            if (flag2)
            {
                EntitySet entitySet = this.DetachedEntityKey.GetEntitySet(this.ObjectContext.MetadataWorkspace);
                objectStateManager.AddKeyEntry(this.DetachedEntityKey, entitySet);
            }
            EntityKey entityKey = this.WrappedOwner.EntityKey;

            if ((object)entityKey == null)
            {
                throw Error.EntityKey_UnexpectedNull();
            }
            RelationshipWrapper wrapper = new RelationshipWrapper((AssociationSet)this.RelationshipSet, this.RelationshipNavigation.From, entityKey, this.RelationshipNavigation.To, this.DetachedEntityKey);

            objectStateManager.AddNewRelation(wrapper, doAttach ? EntityState.Unchanged : EntityState.Added);
        }
コード例 #2
0
        internal RelationshipEntry(ObjectStateManager cache, EntityState state, RelationshipWrapper relationshipWrapper)
            : base(cache, null, state)
        {
            Debug.Assert(null != relationshipWrapper, "null RelationshipWrapper");
            Debug.Assert(EntityState.Added == state ||
                         EntityState.Unchanged == state ||
                         EntityState.Deleted == state,
                         "invalid EntityState");

            base._entitySet = relationshipWrapper.AssociationSet;
            _relationshipWrapper = relationshipWrapper;
        }
コード例 #3
0
        private void IncludeEntityKey(bool doAttach)
        {
            ObjectStateManager manager = this.ObjectContext.ObjectStateManager;

            bool        addNewRelationship = false;
            bool        addKeyEntry        = false;
            EntityEntry existingEntry      = manager.FindEntityEntry(DetachedEntityKey);

            if (existingEntry == null)
            {
                // add new key entry and create a relationship with it
                addKeyEntry        = true;
                addNewRelationship = true;
            }
            else
            {
                if (existingEntry.IsKeyEntry)
                {
                    // We have an existing key entry, so just need to add a relationship with it

                    // We know the target end of this relationship is 1..1 or 0..1 since it is a reference, so if the source end is also not Many, we have a 1-to-1
                    if (FromEndProperty.RelationshipMultiplicity != RelationshipMultiplicity.Many)
                    {
                        // before we add a new relationship to this key entry, make sure it's not already related to something else
                        // We have to explicitly do this here because there are no other checks to make sure a key entry in a 1-to-1 doesn't end up in two of the same relationship
                        foreach (RelationshipEntry relationshipEntry in this.ObjectContext.ObjectStateManager.FindRelationshipsByKey(DetachedEntityKey))
                        {
                            // only care about relationships in the same AssociationSet and where the key is playing the same role that it plays in this EntityReference
                            if (relationshipEntry.IsSameAssociationSetAndRole((AssociationSet)RelationshipSet, (AssociationEndMember)ToEndMember, DetachedEntityKey) &&
                                relationshipEntry.State != EntityState.Deleted)
                            {
                                throw EntityUtil.EntityConflictsWithKeyEntry();
                            }
                        }
                    }

                    addNewRelationship = true;
                }
                else
                {
                    IEntityWrapper wrappedTarget = existingEntry.WrappedEntity;

                    // Verify that the target entity is in a valid state for adding a relationship
                    if (existingEntry.State == EntityState.Deleted)
                    {
                        throw EntityUtil.UnableToAddRelationshipWithDeletedEntity();
                    }

                    // We know the target end of this relationship is 1..1 or 0..1 since it is a reference, so if the source end is also not Many, we have a 1-to-1
                    RelatedEnd relatedEnd = wrappedTarget.RelationshipManager.GetRelatedEndInternal(RelationshipName, RelationshipNavigation.From);
                    if (FromEndProperty.RelationshipMultiplicity != RelationshipMultiplicity.Many && !relatedEnd.IsEmpty())
                    {
                        // Make sure the target entity is not already related to something else.
                        // devnote: The call to Add below does *not* do this check for the fixup case, so if it's not done here, no failure will occur
                        //          and existing relationships may be deleted unexpectedly. RelatedEnd.Include should not remove existing relationships, only add new ones.
                        throw EntityUtil.EntityConflictsWithKeyEntry();
                    }

                    // We have an existing entity with the same key, just hook up the related ends
                    this.Add(wrappedTarget,
                             applyConstraints: true,
                             addRelationshipAsUnchanged: doAttach,
                             relationshipAlreadyExists: false,
                             allowModifyingOtherEndOfRelationship: true,
                             forceForeignKeyChanges: true);

                    // add to the list of promoted key references so we can cleanup if a failure occurs later
                    manager.TransactionManager.PopulatedEntityReferences.Add(this);
                }
            }

            // For FKs, don't create a key entry and don't create a relationship
            if (addNewRelationship && !IsForeignKey)
            {
                // devnote: If we add any validation here, it needs to go here before adding the key entry,
                //          otherwise we have to clean up that entry if the validation fails

                if (addKeyEntry)
                {
                    EntitySet targetEntitySet = DetachedEntityKey.GetEntitySet(this.ObjectContext.MetadataWorkspace);
                    manager.AddKeyEntry(DetachedEntityKey, targetEntitySet);
                }

                EntityKey ownerKey = WrappedOwner.EntityKey;
                EntityUtil.CheckEntityKeyNull(ownerKey);
                RelationshipWrapper wrapper = new RelationshipWrapper((AssociationSet)RelationshipSet,
                                                                      RelationshipNavigation.From, ownerKey, RelationshipNavigation.To, DetachedEntityKey);
                manager.AddNewRelation(wrapper, doAttach ? EntityState.Unchanged : EntityState.Added);
            }
        }
コード例 #4
0
 /// <summary>
 ///     Update one of the ends of the relationship
 /// </summary>
 internal void ChangeRelatedEnd(EntityKey oldKey, EntityKey newKey)
 {
     if (oldKey.Equals(Key0))
     {
         if (oldKey.Equals(Key1))
         {
             // self-reference
             RelationshipWrapper = new RelationshipWrapper(RelationshipWrapper.AssociationSet, newKey);
         }
         else
         {
             RelationshipWrapper = new RelationshipWrapper(RelationshipWrapper, 0, newKey);
         }
     }
     else
     {
         RelationshipWrapper = new RelationshipWrapper(RelationshipWrapper, 1, newKey);
     }
 }
コード例 #5
0
        internal override void Reset()
        {
            _relationshipWrapper = null;

            base.Reset();
        }
コード例 #6
0
        internal void SetEntityKey(EntityKey value, bool forceFixup)
        {
            if (value != null && value == EntityKey
                && (ReferenceValue.Entity != null || (ReferenceValue.Entity == null && !forceFixup)))
            {
                // "no-op" -- this is not really no-op in the attached case, because at a minimum we have to do a key lookup,
                // worst case we have to review all relationships for the owner entity
                // However, if we don't do this, we can get into a scenario where we are setting the key to the same thing it's already set to
                // and this could have side effects, especially with RI constraints and cascade delete. We don't want to delete something
                // and then add it back, if that deleting could have additional unexpected effects. Don't bother doing this check if value is
                // null, because EntityKey could be null even if there are Added/Unchanged relationships, if the target entity has a temporary key.
                // In that case, we still need to delete that existing relationship, so it's not a no-op
                return;
            }

            if (ObjectContext != null
                && !UsingNoTracking)
            {
                Debug.Assert(WrappedOwner.Entity != null, "Unexpected null Owner on EntityReference attached to a context");

                // null is a valid value for the EntityKey, but temporary and special keys are not    
                // devnote: Can't check this on detached references because this property could be set to a temp key during deserialization,
                //          if the key hasn't finished deserializing yet.
                if (value != null
                    && !IsValidEntityKeyType(value))
                {
                    throw new ArgumentException(Strings.EntityReference_CannotSetSpecialKeys, "value");
                }

                if (value == null)
                {
                    if (AttemptToNullFKsOnRefOrKeySetToNull())
                    {
                        DetachedEntityKey = null;
                    }
                    else
                    {
                        ReferenceValue = NullEntityWrapper.NullWrapper;
                    }
                }
                else
                {
                    // Verify that the key has the right EntitySet for this RelationshipSet
                    var targetEntitySet = value.GetEntitySet(ObjectContext.MetadataWorkspace);
                    CheckRelationEntitySet(targetEntitySet);
                    value.ValidateEntityKey(ObjectContext.MetadataWorkspace, targetEntitySet, true /*isArgumentException */, "value");

                    var manager = ObjectContext.ObjectStateManager;

                    // If we already have an entry with this key, we just need to create a relationship with it
                    var addNewRelationship = false;
                    // If we don't already have any matching entries for this key, we'll have to create a new entry
                    var addKeyEntry = false;
                    var targetEntry = manager.FindEntityEntry(value);
                    if (targetEntry != null)
                    {
                        // If it's not a key entry, just use the entity to set this reference's Value
                        if (!targetEntry.IsKeyEntry)
                        {
                            // Delegate to the Value property to clear any existing relationship
                            // and to add the new one. This will fire the appropriate events and
                            // ensure that the related ends are connected.

                            // It has to be a TEntity since we already verified that the EntitySet is correct above
                            ReferenceValue = targetEntry.WrappedEntity;
                        }
                        else
                        {
                            // if the existing entry is a key entry, we just need to
                            // add a new relationship between the source entity and that key
                            addNewRelationship = true;
                        }
                    }
                    else
                    {
                        // no entry exists, so we'll need to add a key along with the relationship
                        addKeyEntry = !IsForeignKey;
                        addNewRelationship = true;
                    }

                    if (addNewRelationship)
                    {
                        var ownerKey = ValidateOwnerWithRIConstraints(
                            targetEntry == null ? null : targetEntry.WrappedEntity, value, checkBothEnds: true);

                        // Verify that the owner is in a valid state for adding a relationship
                        ValidateStateForAdd(WrappedOwner);

                        if (addKeyEntry)
                        {
                            manager.AddKeyEntry(value, targetEntitySet);
                        }

                        // First, clear any existing relationships
                        manager.TransactionManager.EntityBeingReparented = WrappedOwner.Entity;
                        try
                        {
                            ClearCollectionOrRef(null, null, /*doCascadeDelete*/ false);
                        }
                        finally
                        {
                            manager.TransactionManager.EntityBeingReparented = null;
                        }

                        // Then add the new one
                        if (IsForeignKey)
                        {
                            DetachedEntityKey = value;
                            // Update the FK values in this entity
                            if (IsDependentEndOfReferentialConstraint(false))
                            {
                                UpdateForeignKeyValues(WrappedOwner, value);
                            }
                        }
                        else
                        {
                            var wrapper = new RelationshipWrapper(
                                (AssociationSet)RelationshipSet, RelationshipNavigation.From, ownerKey, RelationshipNavigation.To, value);
                            // Add the relationship in the unchanged state if
                            var relationshipState = EntityState.Added;

                            // If this is an unchanged/modified dependent end of a relationship and we are allowing the EntityKey to be set
                            // create the relationship in the Unchanged state because the state must "match" the dependent end state
                            if (!ownerKey.IsTemporary
                                && IsDependentEndOfReferentialConstraint(false))
                            {
                                relationshipState = EntityState.Unchanged;
                            }
                            manager.AddNewRelation(wrapper, relationshipState);
                        }
                    }
                }
            }
            else
            {
                // Just set the field for detached object -- during Attach/Add we will make sure this value
                // is not in conflict if the EntityReference contains a real entity. We cannot always determine the
                // EntityKey for any real entity in the detached state, so we don't bother to do it here.
                DetachedEntityKey = value;
            }
        }
コード例 #7
0
ファイル: shaper.cs プロジェクト: zqb971/EntityFramework6
        // <summary>
        // Call to ensure a target entities key is added into the state manager
        // properly
        // </summary>
        public IEntityWrapper HandleRelationshipSpan(
            IEntityWrapper wrappedEntity, EntityKey targetKey, AssociationEndMember targetMember)
        {
            if (null == wrappedEntity.Entity)
            {
                return(wrappedEntity);
            }
            DebugCheck.NotNull(targetMember);
            Debug.Assert(
                targetMember.RelationshipMultiplicity == RelationshipMultiplicity.One ||
                targetMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne);

            var sourceKey    = wrappedEntity.EntityKey;
            var sourceMember = MetadataHelper.GetOtherAssociationEnd(targetMember);

            CheckClearedEntryOnSpan(targetKey, wrappedEntity, sourceKey, targetMember);

            if (null != (object)targetKey)
            {
                EntitySet targetEntitySet;

                var associationSet = Context.MetadataWorkspace.MetadataOptimization.FindCSpaceAssociationSet(
                    (AssociationType)targetMember.DeclaringType, targetMember.Name,
                    targetKey.EntitySetName, targetKey.EntityContainerName, out targetEntitySet);
                Debug.Assert(associationSet != null, "associationSet should not be null");

                var         manager = Context.ObjectStateManager;
                EntityState newEntryState;
                // If there is an existing relationship entry, update it based on its current state and the MergeOption, otherwise add a new one
                if (
                    !ObjectStateManager.TryUpdateExistingRelationships(
                        Context, MergeOption, associationSet, sourceMember, sourceKey, wrappedEntity, targetMember, targetKey,
                        /*setIsLoaded*/ true, out newEntryState))
                {
                    // Try to find a state entry for the target key
                    var targetEntry = manager.GetOrAddKeyEntry(targetKey, targetEntitySet);

                    // For 1-1 relationships we have to take care of the relationships of targetEntity
                    var needNewRelationship = true;
                    switch (sourceMember.RelationshipMultiplicity)
                    {
                    case RelationshipMultiplicity.ZeroOrOne:
                    case RelationshipMultiplicity.One:
                        // devnote: targetEntry can be a key entry (targetEntry.Entity == null),
                        // but it that case this parameter won't be used in TryUpdateExistingRelationships
                        needNewRelationship = !ObjectStateManager.TryUpdateExistingRelationships(
                            Context,
                            MergeOption,
                            associationSet,
                            targetMember,
                            targetKey,
                            targetEntry.WrappedEntity,
                            sourceMember,
                            sourceKey,
                            setIsLoaded: true,
                            newEntryState: out newEntryState);

                        // It is possible that as part of removing existing relationships, the key entry was deleted
                        // If that is the case, recreate the key entry
                        if (targetEntry.State
                            == EntityState.Detached)
                        {
                            targetEntry = manager.AddKeyEntry(targetKey, targetEntitySet);
                        }
                        break;

                    case RelationshipMultiplicity.Many:
                        // we always need a new relationship with Many-To-Many, if there was no exact match between these two entities, so do nothing
                        break;

                    default:
                        Debug.Assert(false, "Unexpected sourceMember.RelationshipMultiplicity");
                        break;
                    }

                    if (needNewRelationship)
                    {
                        // If the target entry is a key entry, then we need to add a relation
                        //   between the source and target entries
                        // If we are in a state where we just need to add a new Deleted relation, we
                        //   only need to do that and not touch the related ends
                        // If the target entry is a full entity entry, then we need to add
                        //   the target entity to the source collection or reference
                        if (targetEntry.IsKeyEntry ||
                            newEntryState == EntityState.Deleted)
                        {
                            // Add a relationship between the source entity and the target key entry
                            var wrapper = new RelationshipWrapper(
                                associationSet, sourceMember.Name, sourceKey, targetMember.Name, targetKey);
                            manager.AddNewRelation(wrapper, newEntryState);
                        }
                        else
                        {
                            Debug.Assert(!targetEntry.IsRelationship, "how IsRelationship?");
                            if (targetEntry.State
                                != EntityState.Deleted)
                            {
                                // The entry contains an entity, do collection or reference fixup
                                // This will also try to create a new relationship entry or will revert the delete on an existing deleted relationship
                                ObjectStateManager.AddEntityToCollectionOrReference(
                                    MergeOption, wrappedEntity, sourceMember,
                                    targetEntry.WrappedEntity,
                                    targetMember,
                                    setIsLoaded: true,
                                    relationshipAlreadyExists: false,
                                    inKeyEntryPromotion: false);
                            }
                            else
                            {
                                // if the target entry is deleted, then the materializer needs to create a deleted relationship
                                // between the entity and the target entry so that if the entity is deleted, the update
                                // pipeline can find the relationship (even though it is deleted)
                                var wrapper = new RelationshipWrapper(
                                    associationSet, sourceMember.Name, sourceKey, targetMember.Name, targetKey);
                                manager.AddNewRelation(wrapper, EntityState.Deleted);
                            }
                        }
                    }
                }
            }
            else
            {
                RelatedEnd relatedEnd;
                if (TryGetRelatedEnd(
                        wrappedEntity, (AssociationType)targetMember.DeclaringType, sourceMember.Name, targetMember.Name, out relatedEnd))
                {
                    SetIsLoadedForSpan(relatedEnd, false);
                }
            }

            // else there is nothing else for us to do, the relationship has been handled already
            return(wrappedEntity);
        }
コード例 #8
0
        internal void SetEntityKey(EntityKey value, bool forceFixup)
        {
            if (value != null && value == EntityKey && (ReferenceValue.Entity != null || (ReferenceValue.Entity == null && !forceFixup)))
            {
                // "no-op" -- this is not really no-op in the attached case, because at a minimum we have to do a key lookup,
                // worst case we have to review all relationships for the owner entity
                // However, if we don't do this, we can get into a scenario where we are setting the key to the same thing it's already set to
                // and this could have side effects, especially with RI constraints and cascade delete. We don't want to delete something
                // and then add it back, if that deleting could have additional unexpected effects. Don't bother doing this check if value is
                // null, because EntityKey could be null even if there are Added/Unchanged relationships, if the target entity has a temporary key.
                // In that case, we still need to delete that existing relationship, so it's not a no-op
                return;
            }

            if (this.ObjectContext != null && !UsingNoTracking)
            {
                Debug.Assert(this.WrappedOwner.Entity != null, "Unexpected null Owner on EntityReference attached to a context");

                // null is a valid value for the EntityKey, but temporary and special keys are not
                // devnote: Can't check this on detached references because this property could be set to a temp key during deserialization,
                //          if the key hasn't finished deserializing yet.
                if (value != null && !IsValidEntityKeyType(value))
                {
                    throw EntityUtil.CannotSetSpecialKeys();
                }

                if (value == null)
                {
                    if (AttemptToNullFKsOnRefOrKeySetToNull())
                    {
                        DetachedEntityKey = null;
                    }
                    else
                    {
                        ReferenceValue = EntityWrapperFactory.NullWrapper;
                    }
                }
                else
                {
                    // Verify that the key has the right EntitySet for this RelationshipSet
                    EntitySet targetEntitySet = value.GetEntitySet(ObjectContext.MetadataWorkspace);
                    CheckRelationEntitySet(targetEntitySet);
                    value.ValidateEntityKey(ObjectContext.MetadataWorkspace, targetEntitySet, true /*isArgumentException */, "value");

                    ObjectStateManager manager = this.ObjectContext.ObjectStateManager;

                    // If we already have an entry with this key, we just need to create a relationship with it
                    bool addNewRelationship = false;
                    // If we don't already have any matching entries for this key, we'll have to create a new entry
                    bool        addKeyEntry = false;
                    EntityEntry targetEntry = manager.FindEntityEntry(value);
                    if (targetEntry != null)
                    {
                        // If it's not a key entry, just use the entity to set this reference's Value
                        if (!targetEntry.IsKeyEntry)
                        {
                            // Delegate to the Value property to clear any existing relationship
                            // and to add the new one. This will fire the appropriate events and
                            // ensure that the related ends are connected.

                            // It has to be a TEntity since we already verified that the EntitySet is correct above
                            this.ReferenceValue = targetEntry.WrappedEntity;
                        }
                        else
                        {
                            // if the existing entry is a key entry, we just need to
                            // add a new relationship between the source entity and that key
                            addNewRelationship = true;
                        }
                    }
                    else
                    {
                        // no entry exists, so we'll need to add a key along with the relationship
                        addKeyEntry        = !IsForeignKey;
                        addNewRelationship = true;
                    }

                    if (addNewRelationship)
                    {
                        EntityKey ownerKey = ValidateOwnerWithRIConstraints(targetEntry == null ? null : targetEntry.WrappedEntity, value, checkBothEnds: true);

                        // Verify that the owner is in a valid state for adding a relationship
                        ValidateStateForAdd(this.WrappedOwner);

                        if (addKeyEntry)
                        {
                            manager.AddKeyEntry(value, targetEntitySet);
                        }

                        // First, clear any existing relationships
                        manager.TransactionManager.EntityBeingReparented = WrappedOwner.Entity;
                        try
                        {
                            ClearCollectionOrRef(null, null, /*doCascadeDelete*/ false);
                        }
                        finally
                        {
                            manager.TransactionManager.EntityBeingReparented = null;
                        }

                        // Then add the new one
                        if (IsForeignKey)
                        {
                            DetachedEntityKey = value;
                            // Update the FK values in this entity
                            if (IsDependentEndOfReferentialConstraint(false))
                            {
                                UpdateForeignKeyValues(WrappedOwner, value);
                            }
                        }
                        else
                        {
                            RelationshipWrapper wrapper = new RelationshipWrapper((AssociationSet)RelationshipSet, RelationshipNavigation.From, ownerKey, RelationshipNavigation.To, value);
                            // Add the relationship in the unchanged state if
                            EntityState relationshipState = EntityState.Added;

                            // If this is an unchanged/modified dependent end of a relationship and we are allowing the EntityKey to be set
                            // create the relationship in the Unchanged state because the state must "match" the dependent end state
                            if (!ownerKey.IsTemporary && IsDependentEndOfReferentialConstraint(false))
                            {
                                relationshipState = EntityState.Unchanged;
                            }
                            manager.AddNewRelation(wrapper, relationshipState);
                        }
                    }
                }
            }
            else
            {
                // Just set the field for detached object -- during Attach/Add we will make sure this value
                // is not in conflict if the EntityReference contains a real entity. We cannot always determine the
                // EntityKey for any real entity in the detached state, so we don't bother to do it here.
                DetachedEntityKey = value;
            }
        }
コード例 #9
0
        public IEntityWrapper HandleRelationshipSpan(
            IEntityWrapper wrappedEntity,
            EntityKey targetKey,
            AssociationEndMember targetMember)
        {
            if (wrappedEntity.Entity == null)
            {
                return(wrappedEntity);
            }
            EntityKey            entityKey           = wrappedEntity.EntityKey;
            AssociationEndMember otherAssociationEnd = MetadataHelper.GetOtherAssociationEnd(targetMember);

            this.CheckClearedEntryOnSpan((object)targetKey, wrappedEntity, entityKey, targetMember);
            if ((object)targetKey != null)
            {
                EntitySet          endEntitySet;
                AssociationSet     cspaceAssociationSet = this.Context.MetadataWorkspace.MetadataOptimization.FindCSpaceAssociationSet((AssociationType)targetMember.DeclaringType, targetMember.Name, targetKey.EntitySetName, targetKey.EntityContainerName, out endEntitySet);
                ObjectStateManager objectStateManager   = this.Context.ObjectStateManager;
                EntityState        newEntryState;
                if (!ObjectStateManager.TryUpdateExistingRelationships(this.Context, this.MergeOption, cspaceAssociationSet, otherAssociationEnd, entityKey, wrappedEntity, targetMember, targetKey, true, out newEntryState))
                {
                    EntityEntry entityEntry = objectStateManager.GetOrAddKeyEntry(targetKey, endEntitySet);
                    bool        flag        = true;
                    switch (otherAssociationEnd.RelationshipMultiplicity)
                    {
                    case RelationshipMultiplicity.ZeroOrOne:
                    case RelationshipMultiplicity.One:
                        flag = !ObjectStateManager.TryUpdateExistingRelationships(this.Context, this.MergeOption, cspaceAssociationSet, targetMember, targetKey, entityEntry.WrappedEntity, otherAssociationEnd, entityKey, true, out newEntryState);
                        if (entityEntry.State == EntityState.Detached)
                        {
                            entityEntry = objectStateManager.AddKeyEntry(targetKey, endEntitySet);
                            break;
                        }
                        break;
                    }
                    if (flag)
                    {
                        if (entityEntry.IsKeyEntry || newEntryState == EntityState.Deleted)
                        {
                            RelationshipWrapper wrapper = new RelationshipWrapper(cspaceAssociationSet, otherAssociationEnd.Name, entityKey, targetMember.Name, targetKey);
                            objectStateManager.AddNewRelation(wrapper, newEntryState);
                        }
                        else if (entityEntry.State != EntityState.Deleted)
                        {
                            ObjectStateManager.AddEntityToCollectionOrReference(this.MergeOption, wrappedEntity, otherAssociationEnd, entityEntry.WrappedEntity, targetMember, true, false, false);
                        }
                        else
                        {
                            RelationshipWrapper wrapper = new RelationshipWrapper(cspaceAssociationSet, otherAssociationEnd.Name, entityKey, targetMember.Name, targetKey);
                            objectStateManager.AddNewRelation(wrapper, EntityState.Deleted);
                        }
                    }
                }
            }
            else
            {
                RelatedEnd relatedEnd;
                if (this.TryGetRelatedEnd(wrappedEntity, (AssociationType)targetMember.DeclaringType, otherAssociationEnd.Name, targetMember.Name, out relatedEnd))
                {
                    this.SetIsLoadedForSpan(relatedEnd, false);
                }
            }
            return(wrappedEntity);
        }
コード例 #10
0
 internal void SetEntityKey(EntityKey value, bool forceFixup)
 {
     if (value != (EntityKey)null && value == this.EntityKey && (this.ReferenceValue.Entity != null || this.ReferenceValue.Entity == null && !forceFixup))
     {
         return;
     }
     if (this.ObjectContext != null && !this.UsingNoTracking)
     {
         if (value != (EntityKey)null && !RelatedEnd.IsValidEntityKeyType(value))
         {
             throw new ArgumentException(Strings.EntityReference_CannotSetSpecialKeys, nameof(value));
         }
         if (value == (EntityKey)null)
         {
             if (this.AttemptToNullFKsOnRefOrKeySetToNull())
             {
                 this.DetachedEntityKey = (EntityKey)null;
             }
             else
             {
                 this.ReferenceValue = NullEntityWrapper.NullWrapper;
             }
         }
         else
         {
             EntitySet entitySet = value.GetEntitySet(this.ObjectContext.MetadataWorkspace);
             this.CheckRelationEntitySet(entitySet);
             value.ValidateEntityKey(this.ObjectContext.MetadataWorkspace, entitySet, true, nameof(value));
             ObjectStateManager objectStateManager = this.ObjectContext.ObjectStateManager;
             bool        flag1       = false;
             bool        flag2       = false;
             EntityEntry entityEntry = objectStateManager.FindEntityEntry(value);
             if (entityEntry != null)
             {
                 if (!entityEntry.IsKeyEntry)
                 {
                     this.ReferenceValue = entityEntry.WrappedEntity;
                 }
                 else
                 {
                     flag1 = true;
                 }
             }
             else
             {
                 flag2 = !this.IsForeignKey;
                 flag1 = true;
             }
             if (!flag1)
             {
                 return;
             }
             EntityKey key0 = this.ValidateOwnerWithRIConstraints(entityEntry == null ? (IEntityWrapper)null : entityEntry.WrappedEntity, value, true);
             this.ValidateStateForAdd(this.WrappedOwner);
             if (flag2)
             {
                 objectStateManager.AddKeyEntry(value, entitySet);
             }
             objectStateManager.TransactionManager.EntityBeingReparented = this.WrappedOwner.Entity;
             try
             {
                 this.ClearCollectionOrRef((IEntityWrapper)null, (RelationshipNavigation)null, false);
             }
             finally
             {
                 objectStateManager.TransactionManager.EntityBeingReparented = (object)null;
             }
             if (this.IsForeignKey)
             {
                 this.DetachedEntityKey = value;
                 if (!this.IsDependentEndOfReferentialConstraint(false))
                 {
                     return;
                 }
                 this.UpdateForeignKeyValues(this.WrappedOwner, value);
             }
             else
             {
                 RelationshipWrapper wrapper      = new RelationshipWrapper((AssociationSet)this.RelationshipSet, this.RelationshipNavigation.From, key0, this.RelationshipNavigation.To, value);
                 EntityState         desiredState = EntityState.Added;
                 if (!key0.IsTemporary && this.IsDependentEndOfReferentialConstraint(false))
                 {
                     desiredState = EntityState.Unchanged;
                 }
                 objectStateManager.AddNewRelation(wrapper, desiredState);
             }
         }
     }
     else
     {
         this.DetachedEntityKey = value;
     }
 }