예제 #1
0
파일: Table.cs 프로젝트: keithlemon/Beef
        /// <summary>
        /// Loads the table and column schema details from the database.
        /// </summary>
        /// <param name="db">The <see cref="DatabaseBase"/>.</param>
        /// <param name="refDataSchema">The reference data schema.</param>
        /// <param name="autoSecurity">Indicates whether the UserRole security should be automatically applied.</param>
        /// <param name="skipSqlSpecific">Indicates whether to skip the Microsoft SQL Server specific metadata queries.</param>
        public static List <Table> LoadTablesAndColumns(DatabaseBase db, string refDataSchema = null, bool autoSecurity = false, bool skipSqlSpecific = false)
        {
            var   tables = new List <Table>();
            Table table  = null;

            db.SqlStatement(ResourceManager.GetResourceContent("SelectTableAndColumns.sql")).SelectQuery((dr) =>
            {
                var ct = TableMapper.Default.MapFromDb(dr, Mapper.OperationTypes.Get);
                if (table == null || table.Schema != ct.Schema || table.Name != ct.Name)
                {
                    tables.Add(table = ct);
                }

                table.Columns.Add(ColumnMapper.Default.MapFromDb(dr, Mapper.OperationTypes.Get));
                if (autoSecurity && table.Schema != refDataSchema)
                {
                    table.UserRole = $"{table.Schema}.{table.Name}";
                }
            });

            // Configure all the single column primary and unique constraints.
            foreach (var pks in db.SqlStatement(ResourceManager.GetResourceContent("SelectTablePrimaryKey.sql")).SelectQuery((dr) =>
            {
                return(new
                {
                    ConstraintName = dr.GetValue <string>("CONSTRAINT_NAME"),
                    TableSchema = dr.GetValue <string>("TABLE_SCHEMA"),
                    TableName = dr.GetValue <string>("TABLE_NAME"),
                    TableColumnName = dr.GetValue <string>("COLUMN_NAME"),
                    IsPrimaryKey = dr.GetValue <string>("CONSTRAINT_TYPE").StartsWith("PRIMARY", StringComparison.InvariantCultureIgnoreCase),
                });
            }).GroupBy(x => x.ConstraintName))
            {
                // Only single column unique columns are supported.
                if (pks.Count() > 1 && !pks.First().IsPrimaryKey)
                {
                    continue;
                }

                // Set the column flags as appropriate.
                foreach (var pk in pks)
                {
                    var col = (from t in tables
                               from c in t.Columns
                               where t.Schema == pk.TableSchema && t.Name == pk.TableName && c.Name == pk.TableColumnName
                               select c).Single();

                    if (pk.IsPrimaryKey)
                    {
                        col.IsPrimaryKey = true;
                        col.IsIdentity   = col.DefaultValue != null;
                    }
                    else
                    {
                        col.IsUnique = true;
                    }
                }
            }

            if (!skipSqlSpecific)
            {
                // Configure all the single column foreign keys.
                foreach (var fks in db.SqlStatement(ResourceManager.GetResourceContent("SelectTableForeignKeys.sql")).SelectQuery((dr) =>
                {
                    return(new
                    {
                        ConstraintName = dr.GetValue <string>("FK_CONSTRAINT_NAME"),
                        TableSchema = dr.GetValue <string>("FK_SCHEMA_NAME"),
                        TableName = dr.GetValue <string>("FK_TABLE_NAME"),
                        TableColumnName = dr.GetValue <string>("FK_COLUMN_NAME"),
                        ForeignSchema = dr.GetValue <string>("UQ_SCHEMA_NAME"),
                        ForeignTable = dr.GetValue <string>("UQ_TABLE_NAME"),
                        ForiegnColumn = dr.GetValue <string>("UQ_COLUMN_NAME")
                    });
                }).GroupBy(x => x.ConstraintName).Where(x => x.Count() == 1))
                {
                    var fk  = fks.Single();
                    var col = (from t in tables
                               from c in t.Columns
                               where t.Schema == fk.TableSchema && t.Name == fk.TableName && c.Name == fk.TableColumnName
                               select c).Single();

                    col.ForeignSchema    = fk.ForeignSchema;
                    col.ForeignTable     = fk.ForeignTable;
                    col.ForeignColumn    = fk.ForiegnColumn;
                    col.IsForeignRefData = col.ForeignSchema == refDataSchema;
                }

                db.SqlStatement(ResourceManager.GetResourceContent("SelectTableIdentityColumns.sql")).SelectQuery((dr) =>
                {
                    var t               = tables.Single(x => x.Schema == dr.GetValue <string>("TABLE_SCHEMA") && x.Name == dr.GetValue <string>("TABLE_NAME"));
                    var c               = t.Columns.Single(x => x.Name == dr.GetValue <string>("COLUMN_NAME"));
                    c.IsIdentity        = true;
                    c.IdentitySeed      = 1;
                    c.IdentityIncrement = 1;
                });

                db.SqlStatement(ResourceManager.GetResourceContent("SelectTableAlwaysGeneratedColumns.sql")).SelectQuery((dr) =>
                {
                    var t = tables.Single(x => x.Schema == dr.GetValue <string>("TABLE_SCHEMA") && x.Name == dr.GetValue <string>("TABLE_NAME"));
                    var c = t.Columns.Single(x => x.Name == dr.GetValue <string>("COLUMN_NAME"));
                    t.Columns.Remove(c);
                });

                db.SqlStatement(ResourceManager.GetResourceContent("SelectTableGeneratedColumns.sql")).SelectQuery((dr) =>
                {
                    var t        = tables.Single(x => x.Schema == dr.GetValue <string>("TABLE_SCHEMA") && x.Name == dr.GetValue <string>("TABLE_NAME"));
                    var c        = t.Columns.Single(x => x.Name == dr.GetValue <string>("COLUMN_NAME"));
                    c.IsComputed = true;
                });
            }

            // Auto-determine reference data relationships even where no foreign key defined.
            foreach (var t in tables)
            {
                foreach (var col in t.Columns.Where(x => !x.IsForeignRefData && x.Name.Length > 2 && x.Name.EndsWith("Id")))
                {
                    var rt = tables.Where(x => x.Name != t.Name && x.Name == col.Name.Substring(0, col.Name.Length - 2) && x.Schema == refDataSchema).SingleOrDefault();
                    if (rt != null)
                    {
                        col.ForeignSchema    = rt.Schema;
                        col.ForeignTable     = rt.Name;
                        col.ForeignColumn    = rt.Columns.Where(x => x.IsPrimaryKey).First().Name;
                        col.IsForeignRefData = col.ForeignSchema == refDataSchema;
                    }
                }
            }

            return(tables);
        }