public void ReverseEdges_Throws() { // ReSharper disable once ReturnValueOfPureMethodIsNotUsed // ReSharper disable once AssignNullToNotNullAttribute Assert.Throws <ArgumentNullException>( () => EdgeExtensions.ReverseEdges <int, Edge <int> >(null)); }
public static TryFunc <TVertex, IEnumerable <TEdge> > TreeCyclePoppingRandom <TVertex, TEdge>( this IVertexListGraph <TVertex, TEdge> visitedGraph, TVertex root, IMarkovEdgeChain <TVertex, TEdge> edgeChain) where TEdge : IEdge <TVertex> { Contract.Requires(visitedGraph != null); Contract.Requires(root != null); Contract.Requires(visitedGraph.ContainsVertex(root)); Contract.Ensures(Contract.Result <TryFunc <TVertex, IEnumerable <TEdge> > >() != null); var algo = new CyclePoppingRandomTreeAlgorithm <TVertex, TEdge>(visitedGraph, edgeChain); var predecessorRecorder = new VertexPredecessorRecorderObserver <TVertex, TEdge>(); using (predecessorRecorder.Attach(algo)) algo.Compute(root); var predecessors = predecessorRecorder.VertexPredecessors; return(delegate(TVertex v, out IEnumerable <TEdge> edges) { return EdgeExtensions.TryGetPath(predecessors, v, out edges); }); }
/// <summary> /// Computes a depth first tree. /// </summary> /// <typeparam name="TVertex">The type of the vertex.</typeparam> /// <typeparam name="TEdge">The type of the edge.</typeparam> /// <param name="visitedGraph">The visited graph.</param> /// <param name="root">The root.</param> /// <returns></returns> public static TryFunc <TVertex, IEnumerable <TEdge> > TreeDepthFirstSearch <TVertex, TEdge>( #if !NET20 this #endif IVertexListGraph <TVertex, TEdge> visitedGraph, TVertex root) where TEdge : IEdge <TVertex> { //Contract.Requires(visitedGraph != null); //Contract.Requires(root != null); //Contract.Requires(visitedGraph.ContainsVertex(root)); //Contract.Ensures(//Contract.Result<TryFunc<TVertex, IEnumerable<TEdge>>>() != null); var algo = new DepthFirstSearchAlgorithm <TVertex, TEdge>(visitedGraph); var predecessorRecorder = new VertexPredecessorRecorderObserver <TVertex, TEdge>(); using (predecessorRecorder.Attach(algo)) algo.Compute(root); var predecessors = predecessorRecorder.VertexPredecessors; return(delegate(TVertex v, out IEnumerable <TEdge> edges) { return EdgeExtensions.TryGetPath(predecessors, v, out edges); }); }
public static TryFunc <TVertex, IEnumerable <TEdge> > ShortestPathsAStar <TVertex, TEdge>( #if !NET20 this #endif IVertexAndEdgeListGraph <TVertex, TEdge> visitedGraph, Func <TEdge, double> edgeWeights, Func <TVertex, double> costHeuristic, TVertex source ) where TEdge : IEdge <TVertex> { //Contract.Requires(visitedGraph != null); //Contract.Requires(edgeWeights != null); //Contract.Requires(costHeuristic != null); //Contract.Requires(source != null); var algorithm = new AStarShortestPathAlgorithm <TVertex, TEdge>(visitedGraph, edgeWeights, costHeuristic); var predecessorRecorder = new VertexPredecessorRecorderObserver <TVertex, TEdge>(); using (predecessorRecorder.Attach(algorithm)) algorithm.Compute(source); var predecessors = predecessorRecorder.VertexPredecessors; return(delegate(TVertex v, out IEnumerable <TEdge> edges) { return EdgeExtensions.TryGetPath(predecessors, v, out edges); }); }
} // {return entryEdges.Count;}} public Frame(Dictionary <Edge, FrameWall> frameWalls) { foreach (Edge edge in EdgeExtensions.AllEdges()) { if (!frameWalls.ContainsKey(edge)) { throw new ArgumentException("Missing framewall for an edge"); } } if (frameWalls[Edge.Left].Length != frameWalls[Edge.Right].Length) { throw new ArgumentException("Parallel vertical framewalls have different Lengths"); } if (frameWalls[Edge.Bottom].Length != frameWalls[Edge.Top].Length) { throw new ArgumentException("Parallel horizontal framewalls have different Lengths"); } FrameWalls = frameWalls; Width = frameWalls[Edge.Bottom].Length; Height = frameWalls[Edge.Left].Length; EntryEdges = new List <Edge>(); foreach (KeyValuePair <Edge, FrameWall> item in frameWalls) { if (item.Value.HasEntry) { EntryEdges.Add(item.Key); } } EntryCount = EntryEdges.Count; }
//my edge public FrameRange FrameRangeOff(Edge edge) { FrameWall wall = FrameWalls[edge]; if (!wall.HasEntry) { return(FrameRange.Empty); } Dictionary <Edge, FrameWallRange> frameWallRanges = new Dictionary <Edge, FrameWallRange>(); frameWallRanges[edge.Opposite()] = new FrameWallRange( new FrameWall(0, wall.Entry, 0), new FrameWall(int.MaxValue, wall.Entry, int.MaxValue) ); foreach (Edge missingEdge in EdgeExtensions.AllEdges()) { if (!frameWallRanges.ContainsKey(missingEdge)) { frameWallRanges[missingEdge] = FrameWallRange.All; } } return(new FrameRange(frameWallRanges)); }
public IEnumerable <IEnumerable <TEdge> > HoffmanPavleyRankedShortestPath <TVertex, TEdge>( [PexAssumeNotNull] IBidirectionalGraph <TVertex, TEdge> g, [PexAssumeNotNull] Dictionary <TEdge, double> edgeWeights, TVertex rootVertex, TVertex goalVertex, int pathCount ) where TEdge : IEdge <TVertex> { //GraphConsoleSerializer.DisplayGraph((IEdgeListGraph<TVertex, TEdge>)g); PexAssert.TrueForAll(g.Edges, edgeWeights.ContainsKey); var target = new HoffmanPavleyRankedShortestPathAlgorithm <TVertex, TEdge>(g, e => edgeWeights[e]); target.ShortestPathCount = pathCount; target.Compute(rootVertex, goalVertex); double lastWeight = double.MinValue; foreach (var path in target.ComputedShortestPaths) { Console.WriteLine("path: {0}", Enumerable.Sum(path, e => edgeWeights[e])); double weight = Enumerable.Sum(path, e => edgeWeights[e]); Assert.IsTrue(lastWeight <= weight, "{0} <= {1}", lastWeight, weight); Assert.AreEqual(rootVertex, Enumerable.First(path).Source); Assert.AreEqual(goalVertex, Enumerable.Last(path).Target); Assert.IsTrue(EdgeExtensions.IsPathWithoutCycles <TVertex, TEdge>(path)); lastWeight = weight; } return(target.ComputedShortestPaths); }
private void EnqueueFirstShortestPath( IQueue <DeviationPath> queue, IDictionary <TVertex, TEdge> successors, IDictionary <TVertex, double> distances, TVertex root) { Contract.Requires(queue != null); Contract.Requires(queue.Count == 0); Contract.Requires(successors != null); Contract.Requires(distances != null); Contract.Requires(root != null); var path = new List <TEdge>(); AppendShortestPath( path, successors, root); if (path.Count == 0) { return; // unreachable vertices } if (!EdgeExtensions.HasCycles <TVertex, TEdge>(path)) { this.AddComputedShortestPath(path); } // create deviation paths this.EnqueueDeviationPaths( queue, root, distances, path.ToArray(), 0); }
public void TarjanOfflineLeastCommonAncestorAlgorithm <TVertex, TEdge>( [PexAssumeNotNull] IVertexListGraph <TVertex, TEdge> g, [PexAssumeNotNull] TVertex root, [PexAssumeNotNull] SEquatableEdge <TVertex>[] pairs ) where TEdge : IEdge <TVertex> { var lca = g.OfflineLeastCommonAncestorTarjan(root, pairs); var predecessors = new VertexPredecessorRecorderObserver <TVertex, TEdge>(); var dfs = new DepthFirstSearchAlgorithm <TVertex, TEdge>(g); using (predecessors.Attach(dfs)) dfs.Compute(root); TVertex ancestor; foreach (var pair in pairs) { if (lca(pair, out ancestor)) { Assert.IsTrue(EdgeExtensions.IsPredecessor(predecessors.VertexPredecessors, root, pair.Source)); Assert.IsTrue(EdgeExtensions.IsPredecessor(predecessors.VertexPredecessors, root, pair.Target)); } } }
public static TryFunc <TVertex, IEnumerable <TEdge> > ShortestPathsDijkstra <TVertex, TEdge>( #if !NET20 this #endif IUndirectedGraph <TVertex, TEdge> visitedGraph, Func <TEdge, double> edgeWeights, TVertex source ) where TEdge : IEdge <TVertex> { Contract.Requires(visitedGraph != null); Contract.Requires(edgeWeights != null); Contract.Requires(source != null); var algorithm = new UndirectedDijkstraShortestPathAlgorithm <TVertex, TEdge>(visitedGraph, edgeWeights); var predecessorRecorder = new UndirectedVertexPredecessorRecorderObserver <TVertex, TEdge>(); using (predecessorRecorder.Attach(algorithm)) algorithm.Compute(source); var predecessors = predecessorRecorder.VertexPredecessors; return(delegate(TVertex v, out IEnumerable <TEdge> edges) { return EdgeExtensions.TryGetPath(predecessors, v, out edges); }); }
public override string ToString() { string str = ""; foreach (Edge edge in EdgeExtensions.AllEdges()) { str += edge + ": " + FrameWalls[edge] + "\n"; } str = str.Substring(0, str.Length - 1); return(str); }
public FrameRange(Dictionary <Edge, FrameWallRange> frameWallRanges) { foreach (Edge edge in EdgeExtensions.AllEdges()) { if (!frameWallRanges.ContainsKey(edge)) { throw new ArgumentException("Missing framewall range for an edge"); } } FrameWallRanges = frameWallRanges; }
private void EnqueueDeviationPaths( IQueue <DeviationPath> queue, TVertex root, IDictionary <TVertex, TEdge> successors, IDictionary <TVertex, double> distances, TEdge[] path, int startEdge ) { Contract.Requires(queue != null); Contract.Requires(root != null); Contract.Requires(successors != null); Contract.Requires(distances != null); Contract.Requires(path != null); Contract.Requires(EdgeExtensions.IsAdjacent <TVertex, TEdge>(path[0], root)); Contract.Requires(0 <= startEdge && startEdge < path.Length); TVertex previousVertex = root; double previousWeight = 0; var pathVertices = new Dictionary <TVertex, int>(path.Length); for (int iedge = 0; iedge < path.Length; ++iedge) { var edge = path[iedge]; if (iedge >= startEdge) { this.EnqueueDeviationPaths( queue, distances, path, iedge, previousVertex, previousWeight, pathVertices ); } // update counter previousVertex = edge.Target; previousWeight += this.edgeWeights(edge); // detection of loops if (iedge == 0) { pathVertices[edge.Source] = 0; } // we should really allow only one key if (pathVertices.ContainsKey(edge.Target)) { break; } pathVertices[edge.Target] = 0; } }
private void EnqueueDeviationPaths( IQueue <DeviationPath> queue, IDictionary <TVertex, double> distances, TEdge[] path, int iedge, TVertex previousVertex, double previousWeight, Dictionary <TVertex, int> pathVertices ) { Contract.Requires(queue != null); Contract.Requires(distances != null); Contract.Requires(path != null); var edge = path[iedge]; foreach (var deviationEdge in this.VisitedGraph.OutEdges(previousVertex)) { // skip self edges, // skip equal edges, if (deviationEdge.Equals(edge) || EdgeExtensions.IsSelfEdge <TVertex, TEdge>(deviationEdge)) { continue; } // any edge obviously creating a loop var atarget = deviationEdge.Target; double adistance; if (distances.TryGetValue(atarget, out adistance)) { var deviationWeight = this.DistanceRelaxer.Combine( previousWeight, this.DistanceRelaxer.Combine( this.edgeWeights(deviationEdge), adistance ) ); var deviation = new DeviationPath( path, iedge, deviationEdge, deviationWeight ); queue.Enqueue(deviation); } } }
public IEnumerable <IEnumerable <TEdge> > AllPaths() { List <IEnumerable <TEdge> > es = new List <IEnumerable <TEdge> >(); foreach (var v in this.EndPathVertices) { IEnumerable <TEdge> path; if (EdgeExtensions.TryGetPath(this.vertexPredecessors, v, out path)) { es.Add(path); } } return(es); }
public bool RemoveEdge(TEdge edge) { bool removed = this._adjacentEdges[edge.Source].Remove(edge); if (removed) { if (!EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge)) { this._adjacentEdges[edge.Target].Remove(edge); } this.EdgeCount--; Contract.Assert(this.EdgeCount >= 0); this.OnEdgeRemoved(edge); return(true); } else { return(false); } }
protected override void InternalCompute() { var cancelManager = this.Services.CancelManager; TVertex root; if (!this.TryGetRootVertex(out root)) { throw new InvalidOperationException("root vertex not set"); } if (this.pairs == null) { throw new InvalidOperationException("pairs not set"); } var gpair = GraphExtensions.ToAdjacencyGraph(this.pairs); var disjointSet = new ForestDisjointSet <TVertex>(); var vancestors = new Dictionary <TVertex, TVertex>(); var dfs = new DepthFirstSearchAlgorithm <TVertex, TEdge>(this, this.VisitedGraph, new Dictionary <TVertex, GraphColor>(this.VisitedGraph.VertexCount)); dfs.InitializeVertex += v => disjointSet.MakeSet(v); dfs.DiscoverVertex += v => vancestors[v] = v; dfs.TreeEdge += edge => { disjointSet.Union(edge.Source, edge.Target); vancestors[disjointSet.FindSet(edge.Source)] = edge.Source; }; dfs.FinishVertex += v => { foreach (var e in gpair.OutEdges(v)) { if (dfs.VertexColors[e.Target] == GraphColor.Black) { this.ancestors[EdgeExtensions.ToVertexPair <TVertex, SEquatableEdge <TVertex> >(e)] = vancestors[disjointSet.FindSet(e.Target)]; } } }; // go! dfs.Compute(root); }
public void ReverseEdges() { CollectionAssert.IsEmpty(EdgeExtensions.ReverseEdges <int, Edge <int> >(Enumerable.Empty <Edge <int> >())); var edge1 = new Edge <int>(1, 2); CollectionAssert.AreEqual( new[] { new SReversedEdge <int, Edge <int> >(edge1) }, EdgeExtensions.ReverseEdges <int, Edge <int> >(new[] { edge1 })); var edge2 = new Edge <int>(2, 2); var edge3 = new Edge <int>(3, 1); CollectionAssert.AreEqual( new[] { new SReversedEdge <int, Edge <int> >(edge1), new SReversedEdge <int, Edge <int> >(edge2), new SReversedEdge <int, Edge <int> >(edge3) }, EdgeExtensions.ReverseEdges <int, Edge <int> >(new[] { edge1, edge2, edge3 })); }
public bool AddVerticesAndEdge(TEdge edge) { var sourceEdges = this.AddAndReturnEdges(edge.Source); var targetEdges = this.AddAndReturnEdges(edge.Target); if (!this.AllowParallelEdges) { if (this.ContainsEdgeBetweenVertices(sourceEdges, edge)) { return(false); } } sourceEdges.Add(edge); if (!EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge)) { targetEdges.Add(edge); } this.EdgeCount++; this.OnEdgeAdded(edge); return(true); }
public bool AddEdge(TEdge edge) { var sourceEdges = _adjacentEdges[edge.Source]; if (!AllowParallelEdges) { if (ContainsEdgeBetweenVertices(sourceEdges, edge)) { return(false); } } sourceEdges.Add(edge); if (!EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge)) { var targetEdges = _adjacentEdges[edge.Target]; targetEdges.Add(edge); } EdgeCount++; OnEdgeAdded(edge); return(true); }
protected override void InternalCompute() { var cancelManager = this.Services.CancelManager; TVertex root; if (!this.TryGetRootVertex(out root)) { throw new InvalidOperationException("root vertex not set"); } TVertex goal; if (!this.TryGetGoalVertex(out goal)) { throw new InvalidOperationException("goal vertex not set"); } // start by building the minimum tree starting from the goal vertex. IDictionary <TVertex, TEdge> successors; IDictionary <TVertex, double> distances; this.ComputeMinimumTree(goal, out successors, out distances); if (cancelManager.IsCancelling) { return; } var queue = new FibonacciQueue <DeviationPath, double>(dp => dp.Weight); var vertexCount = this.VisitedGraph.VertexCount; // first shortest path this.EnqueueFirstShortestPath(queue, successors, distances, root); while (queue.Count > 0 && this.ComputedShortestPathCount < this.ShortestPathCount) { if (cancelManager.IsCancelling) { return; } var deviation = queue.Dequeue(); // turn into path var path = new List <TEdge>(); for (int i = 0; i < deviation.DeviationIndex; ++i) { path.Add(deviation.ParentPath[i]); } path.Add(deviation.DeviationEdge); int startEdge = path.Count; this.AppendShortestPath(path, successors, deviation.DeviationEdge.Target); Contract.Assert(deviation.Weight == Enumerable.Sum(path, e => edgeWeights(e))); Contract.Assert(path.Count > 0); // add to list if loopless if (!EdgeExtensions.HasCycles <TVertex, TEdge>(path)) { this.AddComputedShortestPath(path); } // append new deviation paths if (path.Count < vertexCount) { this.EnqueueDeviationPaths( queue, root, successors, distances, path.ToArray(), startEdge ); } } }
public XUndirectedGraph(bool allowParallelEdges) : this(allowParallelEdges, EdgeExtensions.GetUndirectedVertexEquality <TVertex, TEdge>()) { AllowParallelEdges = allowParallelEdges; }
public bool TryGetPath(TVertex vertex, out IEnumerable <TEdge> path) { return(EdgeExtensions.TryGetPath(this.VertexPredecessors, vertex, out path)); }
protected override void InternalCompute() { TVertex root; if (!this.TryGetRootVertex(out root)) { throw new InvalidOperationException("root vertex not set"); } TVertex goal; if (!this.TryGetGoalVertex(out goal)) { throw new InvalidOperationException("goal vertex not set"); } // little shortcut if (root.Equals(goal)) { this.OnGoalReached(); return; // found it } var cancelManager = this.Services.CancelManager; var open = new BinaryHeap <double, TVertex>(this.distanceRelaxer.Compare); var operators = new Dictionary <TEdge, GraphColor>(); var g = this.VisitedGraph; // (1) Place the initial node on Open, with all its operators marked unused. open.Add(0, root); foreach (var edge in g.OutEdges(root)) { operators.Add(edge, GraphColor.White); } while (open.Count > 0) { if (cancelManager.IsCancelling) { return; } // (3) Else, choose an Open node n of lowest cost for expansion var entry = open.RemoveMinimum(); var cost = entry.Key; var n = entry.Value; // (4) if node n is a goal node, terminate with success if (n.Equals(goal)) { this.OnGoalReached(); return; } // (5) else, expand node n, // genarting all successors n' reachable via unused legal operators // compute their cost and delete node n foreach (var edge in g.OutEdges(n)) { if (EdgeExtensions.IsSelfEdge <TVertex, TEdge>(edge)) { continue; // skip self-edges } GraphColor edgeColor; bool hasColor = operators.TryGetValue(edge, out edgeColor); if (!hasColor || edgeColor == GraphColor.White) { var weight = this.edgeWeights(edge); var ncost = this.distanceRelaxer.Combine(cost, weight); // (7) foreach neighboring node of n' mark the operator from n to n' as used // (8) for each node n', if there is no copy of n' in open addit // else save on open on the copy of n' with lowest cose. Mark as used all operators // mak as used in any of the copies operators[edge] = GraphColor.Gray; if (open.MinimumUpdate(ncost, edge.Target)) { this.OnTreeEdge(edge); } } else if (hasColor) { Contract.Assume(edgeColor == GraphColor.Gray); // edge already seen, remove it operators.Remove(edge); } } #if DEBUG this.operatorMaxCount = Math.Max(this.operatorMaxCount, operators.Count); #endif // (6) in a directed graph, generate each predecessor node n via an unused operator // and create dummy nodes for each with costs of infinity foreach (var edge in g.InEdges(n)) { GraphColor edgeColor; if (operators.TryGetValue(edge, out edgeColor) && edgeColor == GraphColor.Gray) { // delete node n operators.Remove(edge); } } } }
protected override void InternalCompute() { var cancelManager = this.Services.CancelManager; // matrix i,j -> path this.data.Clear(); var vertices = this.VisitedGraph.Vertices; var edges = this.VisitedGraph.Edges; // prepare the matrix with initial costs // walk each edge and add entry in cost dictionary foreach (var edge in edges) { var ij = EdgeExtensions.ToVertexPair <TVertex, TEdge>(edge); var cost = this.weights(edge); VertexData value; if (!data.TryGetValue(ij, out value)) { data[ij] = new VertexData(cost, edge); } else if (cost < value.Distance) { data[ij] = new VertexData(cost, edge); } } if (cancelManager.IsCancelling) { return; } // walk each vertices and make sure cost self-cost 0 foreach (var v in vertices) { data[new SEquatableEdge <TVertex>(v, v)] = new VertexData(0, default(TEdge)); } if (cancelManager.IsCancelling) { return; } // iterate k, i, j foreach (var vk in vertices) { if (cancelManager.IsCancelling) { return; } foreach (var vi in vertices) { var ik = new SEquatableEdge <TVertex>(vi, vk); VertexData pathik; if (data.TryGetValue(ik, out pathik)) { foreach (var vj in vertices) { var kj = new SEquatableEdge <TVertex>(vk, vj); VertexData pathkj; if (data.TryGetValue(kj, out pathkj)) { double combined = this.distanceRelaxer.Combine(pathik.Distance, pathkj.Distance); var ij = new SEquatableEdge <TVertex>(vi, vj); VertexData pathij; if (data.TryGetValue(ij, out pathij)) { if (this.distanceRelaxer.Compare(combined, pathij.Distance) < 0) { data[ij] = new VertexData(combined, vk); } } else { data[ij] = new VertexData(combined, vk); } } } } } } // check negative cycles foreach (var vi in vertices) { var ii = new SEquatableEdge <TVertex>(vi, vi); VertexData value; if (data.TryGetValue(ii, out value) && value.Distance < 0) { throw new NegativeCycleGraphException(); } } }
/// <summary> /// Edits the items in the database. /// </summary> /// <param name="serviceProvider">The application service provider.</param> /// <param name="token">The cancellation token for the task.</param> public async Task EditAsync(IServiceProvider serviceProvider, CancellationToken token) { // Check if there weren't any valid items found. if (Items == null) { // Throw an exception. throw new TaskException("No valid items could be found with the provided data."); } // Check if the exception item should be shown. var showExceptionItem = Items.Count() > 1; // Get the total number of batches. var count = Math.Ceiling((double)Items.Count() / ApplicationDbContext.BatchSize); // Go over each batch. for (var index = 0; index < count; index++) { // Check if the cancellation was requested. if (token.IsCancellationRequested) { // Break. break; } // Get the items in the current batch. var batchItems = Items .Skip(index * ApplicationDbContext.BatchSize) .Take(ApplicationDbContext.BatchSize); // Get the IDs of the items in the current batch. var batchIds = batchItems .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id); // Get the IDs of the related entities that appear in the current batch. var batchDatabaseIds = batchItems .Where(item => item.DatabaseEdges != null) .Select(item => item.DatabaseEdges) .SelectMany(item => item) .Where(item => item.Database != null) .Select(item => item.Database) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchDatabaseEdgeFieldIds = batchItems .Where(item => item.DatabaseEdgeFieldEdges != null) .Select(item => item.DatabaseEdgeFieldEdges) .SelectMany(item => item) .Where(item => item.DatabaseEdgeField != null) .Select(item => item.DatabaseEdgeField) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchNodeIds = batchItems .Where(item => item.EdgeNodes != null) .Select(item => item.EdgeNodes) .SelectMany(item => item) .Where(item => item.Node != null) .Select(item => item.Node) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); // Define the list of items to get. var edges = new List <Edge>(); var databases = new List <Database>(); var databaseEdgeFields = new List <DatabaseEdgeField>(); var nodes = new List <Node>(); // Use a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Get the items with the provided IDs. var items = context.Edges .Where(item => !item.DatabaseEdges.Any(item1 => item1.Database.DatabaseType.Name == "Generic")) .Where(item => batchIds.Contains(item.Id)); // Check if there were no items found. if (items == null || !items.Any()) { // Continue. continue; } // Get the items found. edges = items .ToList(); // Get the related entities that appear in the current batch. databaseEdgeFields = context.DatabaseEdgeFields .Where(item => item.Database.DatabaseType.Name != "Generic") .Where(item => batchDatabaseEdgeFieldIds.Contains(item.Id)) .ToList(); databases = context.Databases .Where(item => item.DatabaseType.Name != "Generic") .Where(item => batchDatabaseIds.Contains(item.Id)) .Concat(context.DatabaseEdgeFields .Where(item => item.Database.DatabaseType.Name != "Generic") .Where(item => batchDatabaseEdgeFieldIds.Contains(item.Id)) .Select(item => item.Database)) .Distinct() .ToList(); nodes = context.Nodes .Where(item => !item.DatabaseNodes.Any(item1 => item1.Database.DatabaseType.Name == "Generic")) .Where(item => batchNodeIds.Contains(item.Id)) .ToList(); } // Get the IDs of the items. var edgeIds = edges .Select(item => item.Id); // Save the items to edit. var edgesToEdit = new List <Edge>(); // Go over each of the valid items. foreach (var batchItem in batchItems) { // Get the corresponding item. var edge = edges .FirstOrDefault(item => batchItem.Id == item.Id); // Check if there was no item found. if (edge == null) { // Continue. continue; } // Check if there were no edge nodes provided. if (batchItem.EdgeNodes == null || !batchItem.EdgeNodes.Any()) { // Throw an exception. throw new TaskException("There were no edge nodes provided.", showExceptionItem, batchItem); } // Get the edge nodes. var edgeNodes = batchItem.EdgeNodes .Where(item => item.Node != null) .Where(item => !string.IsNullOrEmpty(item.Node.Id)) .Where(item => item.Type == "Source" || item.Type == "Target") .Select(item => (item.Node.Id, item.Type)) .Distinct() .Where(item => nodes.Any(item1 => item1.Id == item.Item1)) .Select(item => new EdgeNode { NodeId = item.Item1, Type = EnumerationExtensions.GetEnumerationValue <EdgeNodeType>(item.Item2) }); // Check if there were no edge nodes found. if (edgeNodes == null || !edgeNodes.Any(item => item.Type == EdgeNodeType.Source) || !edgeNodes.Any(item => item.Type == EdgeNodeType.Target)) { // Throw an exception. throw new TaskException("There were no edge nodes found.", showExceptionItem, batchItem); } // Check if there were no database edges or database edge field edges provided. if ((batchItem.DatabaseEdges == null || !batchItem.DatabaseEdges.Any()) && (batchItem.DatabaseEdgeFieldEdges == null || !batchItem.DatabaseEdgeFieldEdges.Any())) { // Throw an exception. throw new TaskException("There were no database edges or database edge field edges provided.", showExceptionItem, batchItem); } // Get the database edge field edges. var databaseEdgeFieldEdges = batchItem.DatabaseEdgeFieldEdges != null? batchItem.DatabaseEdgeFieldEdges .Where(item => item.DatabaseEdgeField != null) .Where(item => !string.IsNullOrEmpty(item.DatabaseEdgeField.Id)) .Where(item => !string.IsNullOrEmpty(item.Value)) .Select(item => (item.DatabaseEdgeField.Id, item.Value)) .Distinct() .Where(item => databaseEdgeFields.Any(item1 => item1.Id == item.Item1)) .Select(item => new DatabaseEdgeFieldEdge { DatabaseEdgeFieldId = item.Item1, Value = item.Item2 }) : Enumerable.Empty <DatabaseEdgeFieldEdge>(); // Get the database edges. var databaseEdgeFieldIds = databaseEdgeFieldEdges .Select(item => item.DatabaseEdgeFieldId) .Distinct(); var currentDatabaseEdgeFields = databaseEdgeFields .Where(item => databaseEdgeFieldIds.Contains(item.Id)); var databaseEdges = batchItem.DatabaseEdges != null? batchItem.DatabaseEdges .Where(item => item.Database != null) .Where(item => !string.IsNullOrEmpty(item.Database.Id)) .Select(item => item.Database.Id) .Concat(currentDatabaseEdgeFields .Select(item => item.Database.Id)) .Distinct() .Where(item => databases.Any(item1 => item1.Id == item)) .Select(item => new DatabaseEdge { DatabaseId = item, }) : Enumerable.Empty <DatabaseEdge>(); // Check if there were no database edges found. if (databaseEdges == null || !databaseEdges.Any()) { // Throw an exception. throw new TaskException("There were no database edges found.", showExceptionItem, batchItem); } // Update the edge. edge.Name = string.Concat(nodes.First(item => item.Id == edgeNodes.First(item => item.Type == EdgeNodeType.Source).NodeId).Name, " - ", nodes.First(item => item.Id == edgeNodes.First(item => item.Type == EdgeNodeType.Target).NodeId).Name); edge.Description = batchItem.Description; edge.EdgeNodes = new List <EdgeNode> { edgeNodes.First(item => item.Type == EdgeNodeType.Source), edgeNodes.First(item => item.Type == EdgeNodeType.Target) }; edge.DatabaseEdgeFieldEdges = databaseEdgeFieldEdges.ToList(); edge.DatabaseEdges = databaseEdges.ToList(); // Add the edge to the list. edgesToEdit.Add(edge); } // Delete the dependent entities. await EdgeExtensions.DeleteDependentAnalysesAsync(edgeIds, serviceProvider, token); await EdgeExtensions.DeleteDependentNetworksAsync(edgeIds, serviceProvider, token); // Delete the related entities. await EdgeExtensions.DeleteRelatedEntitiesAsync <EdgeNode>(edgeIds, serviceProvider, token); await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdgeFieldEdge>(edgeIds, serviceProvider, token); await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdge>(edgeIds, serviceProvider, token); // Update the items. await IEnumerableExtensions.EditAsync(edgesToEdit, serviceProvider, token); } }
/// <summary> /// Deletes the items from the database. /// </summary> /// <param name="serviceProvider">The application service provider.</param> /// <param name="token">The cancellation token for the task.</param> public async Task DeleteAsync(IServiceProvider serviceProvider, CancellationToken token) { // Check if there weren't any valid items found. if (Items == null) { // Throw an exception. throw new TaskException("No valid items could be found with the provided data."); } // Get the total number of batches. var count = Math.Ceiling((double)Items.Count() / ApplicationDbContext.BatchSize); // Go over each batch. for (var index = 0; index < count; index++) { // Check if the cancellation was requested. if (token.IsCancellationRequested) { // Break. break; } // Get the items in the current batch. var batchItems = Items .Skip(index * ApplicationDbContext.BatchSize) .Take(ApplicationDbContext.BatchSize); // Get the IDs of the items in the current batch. var batchIds = batchItems.Select(item => item.Id); // Define the list of items to get. var edges = new List <Edge>(); // Use a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Get the items with the provided IDs. var items = context.Edges .Where(item => batchIds.Contains(item.Id)); // Check if there were no items found. if (items == null || !items.Any()) { // Continue. continue; } // Get the items found. edges = items .ToList(); } // Get the IDs of the items. var edgeIds = edges .Select(item => item.Id); // Delete the dependent entities. await EdgeExtensions.DeleteDependentAnalysesAsync(edgeIds, serviceProvider, token); await EdgeExtensions.DeleteDependentNetworksAsync(edgeIds, serviceProvider, token); // Delete the related entities. await EdgeExtensions.DeleteRelatedEntitiesAsync <EdgeNode>(edgeIds, serviceProvider, token); await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdgeFieldEdge>(edgeIds, serviceProvider, token); await EdgeExtensions.DeleteRelatedEntitiesAsync <DatabaseEdge>(edgeIds, serviceProvider, token); // Delete the items. await IEnumerableExtensions.DeleteAsync(edges, serviceProvider, token); } }