/// <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); }); }
/// <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. }