Example #1
0
        public void AddVertices_adds_vertices()
        {
            var model       = new Model();
            var entityTypeA = model.AddEntityType(typeof(A));
            var entityTypeB = model.AddEntityType(typeof(B));

            var graph = new BidirectionalAdjacencyListGraph <EntityType>();

            graph.AddVertices(new[] { entityTypeA, entityTypeB });

            Assert.Equal(new[] { entityTypeA, entityTypeB }, graph.Vertices);
        }
Example #2
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 modifying or adding 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
        protected virtual IEnumerable <List <ModificationCommand> > TopologicalSort([NotNull] IEnumerable <ModificationCommand> commands)
        {
            Check.NotNull(commands, "commands");

            var modificationCommandGraph = new BidirectionalAdjacencyListGraph <ModificationCommand>();

            modificationCommandGraph.AddVertices(commands);

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

            AddForeignKeyEdges(modificationCommandGraph, predecessorsMap);

            return(modificationCommandGraph.TopologicalSort());
        }
Example #3
0
        public void AddEdge_adds_edge()
        {
            var model       = new Model();
            var entityTypeA = model.AddEntityType(typeof(A));
            var entityTypeB = model.AddEntityType(typeof(B));
            var entityTypeC = model.AddEntityType(typeof(C));

            var graph = new BidirectionalAdjacencyListGraph <EntityType>();

            graph.AddVertex(entityTypeA);
            graph.AddVertex(entityTypeB);
            graph.AddVertex(entityTypeC);

            graph.AddEdge(entityTypeA, entityTypeB);
            graph.AddEdge(entityTypeA, entityTypeC);
            graph.AddEdge(entityTypeB, entityTypeC);

            Assert.Equal(new[] { entityTypeB, entityTypeC }, graph.GetOutgoingNeighbours(entityTypeA));
            Assert.Equal(new[] { entityTypeA, entityTypeB }, graph.GetIncomingNeighbours(entityTypeC));
        }
Example #4
0
        private void AddForeignKeyEdges(
            BidirectionalAdjacencyListGraph <ModificationCommand> commandGraph,
            Dictionary <KeyValue, List <ModificationCommand> > predecessorsMap)
        {
            foreach (var command in commandGraph.Vertices)
            {
                if (command.EntityState == EntityState.Modified ||
                    command.EntityState == EntityState.Added)
                {
                    foreach (var stateEntry in command.StateEntries)
                    {
                        foreach (var foreignKey in stateEntry.EntityType.ForeignKeys)
                        {
                            var dependentKeyValue = CreateDependentKeyValue(stateEntry, foreignKey, ValueType.Current);

                            if (dependentKeyValue.Key != EntityKey.NullEntityKey)
                            {
                                List <ModificationCommand> predecessorCommands;
                                if (predecessorsMap.TryGetValue(dependentKeyValue, out predecessorCommands))
                                {
                                    foreach (var predecessor in predecessorCommands)
                                    {
                                        if (predecessor != command)
                                        {
                                            commandGraph.AddEdge(predecessor, command);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // TODO: also examine modified entities here when principal key modification is supported
                if (command.EntityState == EntityState.Deleted)
                {
                    foreach (var stateEntry in command.StateEntries)
                    {
                        foreach (var foreignKey in stateEntry.EntityType.GetReferencingForeignKeys())
                        {
                            var principalKeyValue = CreatePrincipalKeyValue(stateEntry.OriginalValues, foreignKey, ValueType.Original);

                            if (principalKeyValue.Key != EntityKey.NullEntityKey)
                            {
                                List <ModificationCommand> predecessorCommands;
                                if (predecessorsMap.TryGetValue(principalKeyValue, out predecessorCommands))
                                {
                                    foreach (var predecessor in predecessorCommands)
                                    {
                                        if (predecessor != command)
                                        {
                                            commandGraph.AddEdge(predecessor, command);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }