コード例 #1
0
        /// <summary>
        /// Sorts tables by the foreign key dependencies.
        /// </summary>
        /// <param name="databaseSchema">The database schema.</param>
        /// <returns></returns>
        public static IEnumerable<DatabaseTable> TopologicalSort(DatabaseSchema databaseSchema)
        {
            var tables = databaseSchema.Tables;
            var sorter = new TopologicalSorter(tables.Count);

            var indexes = new Dictionary<string, int>();

            //add vertices
            for (var i = 0; i < tables.Count; i++)
            {
                indexes[tables[i].Name] = sorter.AddVertex(i);
            }

            //add edges
            for (var i = 0; i < tables.Count; i++)
            {
                foreach (var t in tables[i].ForeignKeys)
                {
                    //ignore cycles (not relevant here)
                    if (t.RefersToTable == tables[i].Name) continue;
                    //corrupt model
                    if (!indexes.ContainsKey(t.RefersToTable)) continue;

                    sorter.AddEdge(i, indexes[t.RefersToTable]);
                }
            }

            try
            {
                var sortedIndex = sorter.Sort();
                return sortedIndex.Reverse().Select(i => tables[i]);
            }
            catch (InvalidOperationException)
            {
                //Bidirectional foreign keys create a cyclic dependency
                //Topological sort won't work
                //There is no way to sort by insert order for two such tables
                //Just give them the tables back, with those with least foreign keys at the start.
                return tables.OrderBy(t => t.ForeignKeys.Count);
            }
        }