/// <summary>
        /// Traverse an object graph executing a callback on each node.
        /// Depends on Entity Framework Core infrastructure, which may change in future releases.
        /// </summary>
        /// <param name="context">Used to query and save changes to a database</param>
        /// <param name="item">Object that implements ITrackable</param>
        /// <param name="callback">Callback executed on each node in the object graph</param>
        public static void TraverseGraph(this DbContext context, object item,
                                         Action <EntityEntryGraphNode> callback)
        {
            IStateManager             stateManager  = context.Entry(item).GetInfrastructure().StateManager;
            var                       node          = new EntityEntryGraphNode(stateManager.GetOrCreateEntry(item), null, null);
            IEntityEntryGraphIterator graphIterator = new EntityEntryGraphIterator();
            var                       visited       = new HashSet <int>();

            graphIterator.TraverseGraph(node, n =>
            {
                // Check visited
                if (visited.Contains(n.Entry.Entity.GetHashCode()))
                {
                    return(false);
                }

                // Execute callback
                callback(n);

                // Add visited
                visited.Add(n.Entry.Entity.GetHashCode());

                // Return true if node state is null
                return(true);
            });
        }
        /// <summary>
        /// Traverse an object graph executing a callback on each node.
        /// </summary>
        /// <param name="context">Used to query and save changes to a database</param>
        /// <param name="item">Object that implements ITrackable</param>
        /// <param name="callback">Callback executed on each node in the object graph</param>
        public static void TraverseGraph(this DbContext context, object item,
                                         Action <EntityEntryGraphNode> callback)
        {
#pragma warning disable EF1001 // Internal EF Core API usage.
            IStateManager             stateManager  = context.Entry(item).GetInfrastructure().StateManager;
            var                       node          = new EntityEntryGraphNode <object>(stateManager.GetOrCreateEntry(item), null, null, null);
            IEntityEntryGraphIterator graphIterator = new EntityEntryGraphIterator();
#pragma warning restore EF1001 // Internal EF Core API usage.
            var visited = new HashSet <object>();

            graphIterator.TraverseGraph(node, n =>
            {
                // Check visited
                if (visited.Contains(n.Entry.Entity))
                {
                    return(false);
                }

                // Execute callback
                callback(n);

                // Add visited
                visited.Add(n.Entry.Entity);

                // Continue traversal
                return(true);
            });
        }
예제 #3
0
        /// <summary>
        /// Traverse an entity graph executing a callback on each node.
        /// </summary>
        /// <param name="context">The entity graph context.</param>
        /// <param name="entity">The entity to start traversing the graph from.</param>
        /// <param name="callback">The callback executed on each node in the entity graph.</param>
        public static void TraverseGraph(this DbContext context, object entity, Action <EntityEntryGraphNode> callback)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            #pragma warning disable EF1001 // Internal EF Core API usage.
            var graph   = new EntityEntryGraphIterator( );
            var visited = new HashSet <object> ( );
            var entry   = context.Entry(entity).GetInfrastructure( );
            var root    = new EntityEntryGraphNode <object?> (entry, null, null, null);

            graph.TraverseGraph(root, node =>
            {
                if (!visited.Add(node.Entry.Entity))
                {
                    return(false);
                }

                callback(node);
                return(true);
            });
            #pragma warning restore EF1001 // Internal EF Core API usage.
        }