Exemplo n.º 1
0
        public void BatchingTopologicalSort_throws_with_formatted_message_when_cycle_cannot_be_broken()
        {
            const string message = "Formatted cycle";

            var vertexOne = new Vertex {
                Id = 1
            };
            var vertexTwo = new Vertex {
                Id = 2
            };
            var vertexThree = new Vertex {
                Id = 3
            };

            var edgeOne = new Edge {
                Id = 1
            };
            var edgeTwo = new Edge {
                Id = 2
            };
            var edgeThree = new Edge {
                Id = 3
            };

            var graph = new Multigraph <Vertex, Edge>();

            graph.AddVertices(new[] { vertexOne, vertexTwo, vertexThree });

            // 1 -> {2}
            graph.AddEdge(vertexOne, vertexTwo, edgeOne);
            // 2 -> {3}
            graph.AddEdge(vertexTwo, vertexThree, edgeTwo);
            // 3 -> {1}
            graph.AddEdge(vertexThree, vertexOne, edgeThree);

            Dictionary <Vertex, Tuple <Vertex, Vertex, IEnumerable <Edge> > > cycleData = null;

            Func <IEnumerable <Tuple <Vertex, Vertex, IEnumerable <Edge> > >, string> formatter = data =>
            {
                cycleData = data.ToDictionary(entry => entry.Item1);
                return(message);
            };

            Assert.Equal(
                Strings.CircularDependency(message),
                Assert.Throws <InvalidOperationException>(() => graph.BatchingTopologicalSort(formatter)).Message);

            Assert.Equal(3, cycleData.Count());

            Assert.Equal(vertexTwo, cycleData[vertexOne].Item2);
            Assert.Equal(new[] { edgeOne }, cycleData[vertexOne].Item3);

            Assert.Equal(vertexThree, cycleData[vertexTwo].Item2);
            Assert.Equal(new[] { edgeTwo }, cycleData[vertexTwo].Item3);

            Assert.Equal(vertexOne, cycleData[vertexThree].Item2);
            Assert.Equal(new[] { edgeThree }, cycleData[vertexThree].Item3);
        }
Exemplo n.º 2
0
        private static IEnumerable <IEntityType> Sort(IEnumerable <IEntityType> entityTypes)
        {
            var entityTypeGraph = new Multigraph <IEntityType, int>();

            entityTypeGraph.AddVertices(entityTypes);
            foreach (var entityType in entityTypes.Where(et => et.BaseType != null))
            {
                entityTypeGraph.AddEdge(entityType.BaseType !, entityType, 0);
            }

            return(entityTypeGraph.BatchingTopologicalSort().SelectMany(b => b.OrderBy(et => et.Name)));
        }
Exemplo n.º 3
0
        // To avoid violating store constraints the modification commands must be sorted
        // according to these rules:
        //
        // 1. Commands adding rows or modifying the candidate key values (when supported) must precede
        //     commands adding or modifying rows that will be referencing the former
        // 2. Commands deleting rows or modifying the foreign key values must precede
        //     commands deleting rows or modifying the candidate key values (when supported) of rows
        //     that are currently being referenced by the former
        // 3. Commands deleting rows or modifying the foreign key values must precede
        //     commands adding or modifying the foreign key values to the same values
        //     if foreign key is unique
        /// <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>
        protected virtual IReadOnlyList <List <ModificationCommand> > TopologicalSort([NotNull] IEnumerable <ModificationCommand> commands)
        {
            var modificationCommandGraph = new Multigraph <ModificationCommand, IAnnotatable>();

            modificationCommandGraph.AddVertices(commands);

            // The predecessors map allows to populate the graph in linear time
            var predecessorsMap = CreateKeyValuePredecessorMap(modificationCommandGraph);

            AddForeignKeyEdges(modificationCommandGraph, predecessorsMap);

            AddUniqueValueEdges(modificationCommandGraph);

            return(modificationCommandGraph.BatchingTopologicalSort(FormatCycle));
        }
        // To avoid violating store constraints the modification commands must be sorted
        // according to these rules:
        //
        // 1. Commands adding rows or modifying the candidate key values (when supported) must precede
        //     commands adding or modifying rows that will be referencing the former
        // 2. Commands deleting rows or modifying the foreign key values must precede
        //     commands deleting rows or modifying the candidate key values (when supported) of rows
        //     that are currently being referenced by the former
        // 3. Commands deleting rows or modifying the foreign key values must precede
        //     commands adding or modifying the foreign key values to the same values
        //     if foreign key is unique
        protected virtual IReadOnlyList <List <ModificationCommand> > TopologicalSort([NotNull] IEnumerable <ModificationCommand> commands)
        {
            var modificationCommandGraph = new Multigraph <ModificationCommand, IForeignKey>();

            modificationCommandGraph.AddVertices(commands);

            // The predecessors map allows to populate the graph in linear time
            var predecessorsMap = CreateKeyValuePredecessorMap(modificationCommandGraph);

            AddForeignKeyEdges(modificationCommandGraph, predecessorsMap);

            var sortedCommands
                = modificationCommandGraph.BatchingTopologicalSort(data => { return(string.Join(", ", data.Select(d => d.Item3.First()))); });

            return(sortedCommands);
        }
        // To avoid violating store constraints the modification commands must be sorted
        // according to these rules:
        //
        // 1. Commands adding rows or modifying the candidate key values (when supported) must precede
        //     commands adding or modifying rows that will be referencing the former
        // 2. Commands deleting rows or modifying the foreign key values must precede
        //     commands deleting rows or modifying the candidate key values (when supported) of rows
        //     that are currently being referenced by the former
        // 3. Commands deleting rows or modifying the foreign key values must precede
        //     commands adding or modifying the foreign key values to the same values
        //     if foreign key is unique
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected virtual IReadOnlyList<List<ModificationCommand>> TopologicalSort([NotNull] IEnumerable<ModificationCommand> commands)
        {
            var modificationCommandGraph = new Multigraph<ModificationCommand, IForeignKey>();
            modificationCommandGraph.AddVertices(commands);

            // The predecessors map allows to populate the graph in linear time
            var predecessorsMap = CreateKeyValuePredecessorMap(modificationCommandGraph);
            AddForeignKeyEdges(modificationCommandGraph, predecessorsMap);

            var sortedCommands
                = modificationCommandGraph.BatchingTopologicalSort(data => { return string.Join(", ", data.Select(d => d.Item3.First())); });

            return sortedCommands;
        }