Esempio n. 1
0
 private void AddToCollection(InternalEntityEntry entry, INavigation navigation, InternalEntityEntry value, bool fromQuery)
 {
     if (navigation != null)
     {
         _changeDetector.Suspend();
         try
         {
             if (entry.AddToCollection(navigation, value, fromQuery))
             {
                 entry.AddToCollectionSnapshot(navigation, value.Entity);
             }
         }
         finally
         {
             _changeDetector.Resume();
         }
     }
 }
        private void DoFixup(IEnumerable <INavigation> navigations, InternalEntityEntry principalEntry, InternalEntityEntry[] dependentEntries)
        {
            foreach (var navigation in navigations)
            {
                if (navigation.IsDependentToPrincipal())
                {
                    var setter = navigation.GetSetter();

                    foreach (var dependent in dependentEntries)
                    {
                        SetNavigation(setter, dependent.Entity, principalEntry.Entity);
                        dependent.SetRelationshipSnapshotValue(navigation, principalEntry.Entity);
                    }
                }
                else
                {
                    if (navigation.IsCollection())
                    {
                        var collectionAccessor = navigation.GetCollectionAccessor();

                        foreach (var dependent in dependentEntries)
                        {
                            var dependentEntity = dependent.Entity;
                            if (!collectionAccessor.Contains(principalEntry.Entity, dependentEntity))
                            {
                                collectionAccessor.Add(principalEntry.Entity, dependentEntity);
                                principalEntry.AddToCollectionSnapshot(navigation, dependentEntity);
                            }
                        }
                    }
                    else
                    {
                        // TODO: Decide how to handle case where multiple values match non-collection nav prop
                        // Issue #739
                        var value = dependentEntries.Single().Entity;
                        SetNavigation(navigation.GetSetter(), principalEntry.Entity, value);
                        principalEntry.SetRelationshipSnapshotValue(navigation, value);
                    }
                }
            }
        }
 private void AddToCollection(
     InternalEntityEntry entry,
     INavigation navigation,
     IClrCollectionAccessor collectionAccessor,
     object value)
 {
     if (navigation != null)
     {
         _changeDetector.Suspend();
         try
         {
             if (collectionAccessor.Add(entry.Entity, value))
             {
                 entry.AddToCollectionSnapshot(navigation, value);
             }
         }
         finally
         {
             _changeDetector.Resume();
         }
     }
 }
Esempio n. 4
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual void NavigationCollectionChanged(
            InternalEntityEntry entry,
            INavigation navigation,
            IEnumerable <object> added,
            IEnumerable <object> removed)
        {
            if (_inFixup)
            {
                return;
            }

            var foreignKey       = navigation.ForeignKey;
            var stateManager     = entry.StateManager;
            var inverse          = navigation.Inverse;
            var targetEntityType = navigation.TargetEntityType;

            foreach (var oldValue in removed)
            {
                var oldTargetEntry = stateManager.TryGetEntry(oldValue, targetEntityType);

                if (oldTargetEntry != null &&
                    oldTargetEntry.EntityState != EntityState.Detached)
                {
                    try
                    {
                        _inFixup = true;

                        // Null FKs and navigations of dependents that have been removed, unless they
                        // have already been changed.
                        ConditionallyNullForeignKeyProperties(oldTargetEntry, entry, foreignKey);

                        if (inverse != null &&
                            ReferenceEquals(oldTargetEntry[inverse], entry.Entity) &&
                            (!foreignKey.IsOwnership ||
                             (oldTargetEntry.EntityState != EntityState.Deleted &&
                              oldTargetEntry.EntityState != EntityState.Detached)))
                        {
                            SetNavigation(oldTargetEntry, inverse, null, fromQuery: false);
                        }

                        entry.RemoveFromCollectionSnapshot(navigation, oldValue);
                    }
                    finally
                    {
                        _inFixup = false;
                    }
                }
            }

            foreach (var newValue in added)
            {
                var newTargetEntry = stateManager.GetOrCreateEntry(newValue, targetEntityType);
                if (newTargetEntry.EntityState != EntityState.Detached)
                {
                    try
                    {
                        _inFixup = true;

                        // For a dependent added to the collection, remove it from the collection of
                        // the principal entity that it was previously part of
                        var oldPrincipalEntry = stateManager.FindPrincipalUsingRelationshipSnapshot(newTargetEntry, foreignKey);
                        if (oldPrincipalEntry != null &&
                            oldPrincipalEntry != entry)
                        {
                            RemoveFromCollection(oldPrincipalEntry, navigation, newTargetEntry);
                        }

                        // Set the FK properties on added dependents to match this principal
                        SetForeignKeyProperties(newTargetEntry, entry, foreignKey, setModified: true, fromQuery: false);

                        // Set the inverse navigation to point to this principal
                        SetNavigation(newTargetEntry, inverse, entry, fromQuery: false);
                    }
                    finally
                    {
                        _inFixup = false;
                    }
                }
                else
                {
                    stateManager.RecordReferencedUntrackedEntity(newValue, navigation, entry);

                    _attacher.AttachGraph(
                        newTargetEntry,
                        EntityState.Added,
                        EntityState.Modified,
                        forceStateWhenUnknownKey: false);
                }

                entry.AddToCollectionSnapshot(navigation, newValue);
            }
        }
        public virtual void NavigationCollectionChanged(
            InternalEntityEntry entry,
            INavigation navigation,
            ISet <object> added,
            ISet <object> removed)
        {
            if (_inFixup)
            {
                return;
            }

            var foreignKey         = navigation.ForeignKey;
            var stateManager       = entry.StateManager;
            var inverse            = navigation.FindInverse();
            var collectionAccessor = navigation.GetCollectionAccessor();

            foreach (var oldValue in removed)
            {
                var oldTargetEntry = stateManager.TryGetEntry(oldValue);

                if (oldTargetEntry != null &&
                    oldTargetEntry.EntityState != EntityState.Detached)
                {
                    try
                    {
                        _inFixup = true;

                        // Null FKs and navigations of dependents that have been removed, unless they
                        // have already been changed.
                        ConditionallyNullForeignKeyProperties(oldTargetEntry, entry, foreignKey);

                        if (inverse != null &&
                            ReferenceEquals(oldTargetEntry[inverse], entry.Entity))
                        {
                            SetNavigation(oldTargetEntry, inverse, null);
                        }

                        entry.RemoveFromCollectionSnapshot(navigation, oldValue);
                    }
                    finally
                    {
                        _inFixup = false;
                    }
                }
            }

            foreach (var newValue in added)
            {
                var newTargetEntry = stateManager.GetOrCreateEntry(newValue);

                if (newTargetEntry.EntityState != EntityState.Detached)
                {
                    try
                    {
                        _inFixup = true;

                        // For a dpendent added to the collection, remove it from the collection of
                        // the principal entity that it was previously part of
                        var oldPrincipalEntry = stateManager.GetPrincipal(newTargetEntry, foreignKey);
                        if (oldPrincipalEntry != null)
                        {
                            RemoveFromCollection(oldPrincipalEntry, navigation, collectionAccessor, newValue);
                        }

                        // Set the FK properties on added dependents to match this principal
                        SetForeignKeyProperties(newTargetEntry, entry, foreignKey, setModified: true);

                        // Set the inverse navigation to point to this principal
                        SetNavigation(newTargetEntry, inverse, entry.Entity);

                        entry.AddToCollectionSnapshot(navigation, newValue);
                    }
                    finally
                    {
                        _inFixup = false;
                    }
                }
                else
                {
                    _attacher.AttachGraph(newTargetEntry, EntityState.Added);
                }
            }
        }
Esempio n. 6
0
        private void DetectNavigationChange(InternalEntityEntry entry, INavigation navigation)
        {
            var snapshotValue = entry.GetRelationshipSnapshotValue(navigation);
            var currentValue  = entry[navigation];
            var stateManager  = entry.StateManager;

            var added = new HashSet <object>(ReferenceEqualityComparer.Instance);

            if (navigation.IsCollection())
            {
                var snapshotCollection = (IEnumerable)snapshotValue;
                var currentCollection  = (IEnumerable)currentValue;

                var removed = new HashSet <object>(ReferenceEqualityComparer.Instance);
                if (snapshotCollection != null)
                {
                    foreach (var entity in snapshotCollection)
                    {
                        removed.Add(entity);
                    }
                }

                if (currentCollection != null)
                {
                    foreach (var entity in currentCollection)
                    {
                        if (!removed.Remove(entity))
                        {
                            added.Add(entity);
                        }
                    }
                }

                if (added.Any() ||
                    removed.Any())
                {
                    stateManager.Notify.NavigationCollectionChanged(entry, navigation, added, removed);

                    foreach (var addedEntity in added)
                    {
                        entry.AddToCollectionSnapshot(navigation, addedEntity);
                    }

                    foreach (var removedEntity in removed)
                    {
                        entry.RemoveFromCollectionSnapshot(navigation, removedEntity);
                    }
                }
            }
            else if (!ReferenceEquals(currentValue, snapshotValue))
            {
                stateManager.Notify.NavigationReferenceChanged(entry, navigation, snapshotValue, currentValue);

                if (currentValue != null)
                {
                    added.Add(currentValue);
                }

                entry.SetRelationshipSnapshotValue(navigation, currentValue);
            }

            foreach (var addedEntity in added)
            {
                var addedEntry = stateManager.GetOrCreateEntry(addedEntity);
                if (addedEntry.EntityState == EntityState.Detached)
                {
                    _attacher.AttachGraph(addedEntry, EntityState.Added);
                }
            }
        }