public virtual DatabaseSchema GetSchema(DataConnection dataConnection, GetSchemaOptions options = null) { if (options == null) options = new GetSchemaOptions(); IncludedSchemas = options.IncludedSchemas ?? new string[0]; ExcludedSchemas = options.ExcludedSchemas ?? new string[0]; GenerateChar1AsString = options.GenerateChar1AsString; var dbConnection = (DbConnection)dataConnection.Connection; DataTypes = GetDataTypes(dataConnection); List<TableSchema> tables; List<ProcedureSchema> procedures; if (options.GetTables) { tables = ( from t in GetTables(dataConnection) where (IncludedSchemas.Length == 0 || IncludedSchemas.Contains(t.SchemaName)) && (ExcludedSchemas.Length == 0 || !ExcludedSchemas.Contains(t.SchemaName)) select new TableSchema { ID = t.TableID, CatalogName = t.CatalogName, SchemaName = t.SchemaName, TableName = t.TableName, Description = t.Description, IsDefaultSchema = t.IsDefaultSchema, IsView = t.IsView, TypeName = ToValidName(t.TableName), Columns = new List<ColumnSchema>(), ForeignKeys = new List<ForeignKeySchema>() } ).ToList(); var pks = GetPrimaryKeys(dataConnection); #region Columns var columns = from c in GetColumns(dataConnection) join dt in DataTypes on c.DataType equals dt.TypeName into g1 from dt in g1.DefaultIfEmpty() join pk in pks on c.TableID + "." + c.Name equals pk.TableID + "." + pk.ColumnName into g2 from pk in g2.DefaultIfEmpty() join t in tables on c.TableID equals t.ID orderby c.Ordinal select new { t, c, dt, pk }; foreach (var column in columns) { var columnType = column.c.DataType; var systemType = GetSystemType(columnType, column.dt, column.c.Length, column.c.Precision, column.c.Scale); var isNullable = column.c.IsNullable; column.t.Columns.Add(new ColumnSchema { Table = column.t, ColumnName = column.c.Name, ColumnType = column.c.ColumnType ?? GetDbType(columnType, column.dt, column.c.Length, column.c.Precision, column.c.Scale), IsNullable = isNullable, MemberName = ToValidName(column.c.Name), MemberType = ToTypeName(systemType, isNullable), SystemType = systemType ?? typeof(object), DataType = GetDataType(columnType, column.c.ColumnType), SkipOnInsert = column.c.SkipOnInsert || column.c.IsIdentity, SkipOnUpdate = column.c.SkipOnUpdate || column.c.IsIdentity, IsPrimaryKey = column.pk != null, PrimaryKeyOrder = column.pk != null ? column.pk.Ordinal : -1, IsIdentity = column.c.IsIdentity, Description = column.c.Description, }); } #endregion #region FK var fks = GetForeignKeys(dataConnection); foreach (var fk in fks.OrderBy(f => f.Ordinal)) { var thisTable = (from t in tables where t.ID == fk.ThisTableID select t).FirstOrDefault(); var otherTable = (from t in tables where t.ID == fk.OtherTableID select t).FirstOrDefault(); if (thisTable == null || otherTable == null) continue; var thisColumn = (from c in thisTable. Columns where c.ColumnName == fk.ThisColumn select c).Single(); var otherColumn = (from c in otherTable.Columns where c.ColumnName == fk.OtherColumn select c).Single(); var key = thisTable.ForeignKeys.FirstOrDefault(f => f.KeyName == fk.Name); if (key == null) { key = new ForeignKeySchema { KeyName = fk.Name, MemberName = ToValidName(fk.Name), ThisTable = thisTable, OtherTable = otherTable, ThisColumns = new List<ColumnSchema>(), OtherColumns = new List<ColumnSchema>(), CanBeNull = true, }; thisTable.ForeignKeys.Add(key); } key.ThisColumns. Add(thisColumn); key.OtherColumns.Add(otherColumn); } #endregion } else tables = new List<TableSchema>(); if (options.GetProcedures) { #region Procedures var sqlProvider = dataConnection.DataProvider.CreateSqlProvider(); var procs = GetProcedures(dataConnection); var procPparams = GetProcedureParameters(dataConnection); if (procs != null) { procedures = ( from sp in procs where (IncludedSchemas.Length == 0 || IncludedSchemas.Contains(sp.SchemaName)) && (ExcludedSchemas.Length == 0 || !ExcludedSchemas.Contains(sp.SchemaName)) join p in procPparams on sp.ProcedureID equals p.ProcedureID into gr select new ProcedureSchema { CatalogName = sp.CatalogName, SchemaName = sp.SchemaName, ProcedureName = sp.ProcedureName, MemberName = ToValidName(sp.ProcedureName), IsFunction = sp.IsFunction, IsTableFunction = sp.IsTableFunction, IsDefaultSchema = sp.IsDefaultSchema, Parameters = ( from pr in gr join dt in DataTypes on pr.DataType equals dt.TypeName into g1 from dt in g1.DefaultIfEmpty() let systemType = GetSystemType(pr.DataType, dt, pr.Length ?? 0, pr.Precision, pr.Scale) orderby pr.Ordinal select new ParameterSchema { SchemaName = pr.ParameterName, SchemaType = GetDbType(pr.DataType, dt, pr.Length ?? 0, pr.Precision, pr.Scale), IsIn = pr.IsIn, IsOut = pr.IsOut, IsResult = pr.IsResult, Size = pr.Length, ParameterName = ToValidName(pr.ParameterName), ParameterType = ToTypeName(systemType, true), SystemType = systemType ?? typeof(object), DataType = GetDataType(pr.DataType, null) } ).ToList() } into ps where ps.Parameters.All(p => p.SchemaType != "table type") select ps ).ToList(); var current = 1; foreach (var procedure in procedures) { if ((!procedure.IsFunction || procedure.IsTableFunction) && options.LoadProcedure(procedure)) { var catalog = procedure.CatalogName == null ? null : sqlProvider.Convert(procedure.CatalogName, ConvertType.NameToDatabase). ToString(); var schema = procedure.SchemaName == null ? null : sqlProvider.Convert(procedure.SchemaName, ConvertType.NameToOwner). ToString(); var procName = procedure.ProcedureName == null ? null : sqlProvider.Convert(procedure.ProcedureName, ConvertType.NameToQueryTable).ToString(); var commandText = sqlProvider.BuildTableName(new StringBuilder(), catalog, schema, procName).ToString(); CommandType commandType; DataParameter[] parameters; if (procedure.IsTableFunction) { commandText = "SELECT * FROM " + commandText + "("; for (var i = 0; i < procedure.Parameters.Count; i++) { if (i != 0) commandText += ","; commandText += "NULL"; } commandText += ")"; commandType = CommandType.Text; parameters = new DataParameter[0]; } else { commandType = CommandType.StoredProcedure; parameters = procedure.Parameters.Select(p => new DataParameter { Name = p.ParameterName, Value = p.SystemType == typeof(string) ? "" : p.SystemType == typeof(DateTime) ? DateTime.Now : DefaultValue.GetValue(p.SystemType), DataType = p.DataType, Size = p.Size, Direction = p.IsIn ? p.IsOut ? ParameterDirection.InputOutput : ParameterDirection.Input : ParameterDirection.Output }).ToArray(); } { try { var st = GetProcedureSchema(dataConnection, commandText, commandType, parameters); if (st != null) { procedure.ResultTable = new TableSchema { IsProcedureResult = true, TypeName = ToValidName(procedure.ProcedureName + "Result"), ForeignKeys = new List<ForeignKeySchema>(), Columns = GetProcedureResultColumns(st) }; foreach (var column in procedure.ResultTable.Columns) column.Table = procedure.ResultTable; procedure.SimilarTables = ( from t in tables where t.Columns.Count == procedure.ResultTable.Columns.Count let zip = t.Columns.Zip(procedure.ResultTable.Columns, (c1, c2) => new { c1, c2 }) where zip.All(z => z.c1.ColumnName == z.c2.ColumnName && z.c1.SystemType == z.c2.SystemType) select t ).ToList(); } } catch (Exception ex) { procedure.ResultException = ex; } } } options.ProcedureLoadingProgress(procedures.Count, current++); } } else procedures = new List<ProcedureSchema>(); #endregion } else procedures = new List<ProcedureSchema>(); return ProcessSchema(new DatabaseSchema { DataSource = GetDataSourceName(dbConnection), Database = GetDatabaseName (dbConnection), ServerVersion = dbConnection.ServerVersion, Tables = tables, Procedures = procedures, }); }
public virtual DatabaseSchema GetSchema(DataConnection dataConnection, GetSchemaOptions options = null) { if (options == null) { options = new GetSchemaOptions(); } IncludedSchemas = options.IncludedSchemas ?? new string[0]; ExcludedSchemas = options.ExcludedSchemas ?? new string[0]; GenerateChar1AsString = options.GenerateChar1AsString; var dbConnection = (DbConnection)dataConnection.Connection; DataTypes = GetDataTypes(dataConnection); List <TableSchema> tables; List <ProcedureSchema> procedures; if (options.GetTables) { tables = ( from t in GetTables(dataConnection) where (IncludedSchemas.Length == 0 || IncludedSchemas.Contains(t.SchemaName)) && (ExcludedSchemas.Length == 0 || !ExcludedSchemas.Contains(t.SchemaName)) select new TableSchema { ID = t.TableID, CatalogName = t.CatalogName, SchemaName = t.SchemaName, TableName = t.TableName, Description = t.Description, IsDefaultSchema = t.IsDefaultSchema, IsView = t.IsView, TypeName = ToValidName(t.TableName), Columns = new List <ColumnSchema>(), ForeignKeys = new List <ForeignKeySchema>() } ).ToList(); var pks = GetPrimaryKeys(dataConnection); #region Columns var columns = from c in GetColumns(dataConnection) join dt in DataTypes on c.DataType equals dt.TypeName into g1 from dt in g1.DefaultIfEmpty() join pk in pks on c.TableID + "." + c.Name equals pk.TableID + "." + pk.ColumnName into g2 from pk in g2.DefaultIfEmpty() join t in tables on c.TableID equals t.ID orderby c.Ordinal select new { t, c, dt, pk }; foreach (var column in columns) { var columnType = column.c.DataType; var systemType = GetSystemType(columnType, column.dt, column.c.Length, column.c.Precision, column.c.Scale); var isNullable = column.c.IsNullable; column.t.Columns.Add(new ColumnSchema { Table = column.t, ColumnName = column.c.Name, ColumnType = column.c.ColumnType ?? GetDbType(columnType, column.dt, column.c.Length, column.c.Precision, column.c.Scale), IsNullable = isNullable, MemberName = ToValidName(column.c.Name), MemberType = ToTypeName(systemType, isNullable), SystemType = systemType ?? typeof(object), DataType = GetDataType(columnType, column.c.ColumnType), SkipOnInsert = column.c.SkipOnInsert || column.c.IsIdentity, SkipOnUpdate = column.c.SkipOnUpdate || column.c.IsIdentity, IsPrimaryKey = column.pk != null, PrimaryKeyOrder = column.pk != null ? column.pk.Ordinal : -1, IsIdentity = column.c.IsIdentity, Description = column.c.Description, }); } #endregion #region FK var fks = GetForeignKeys(dataConnection); foreach (var fk in fks.OrderBy(f => f.Ordinal)) { var thisTable = (from t in tables where t.ID == fk.ThisTableID select t).FirstOrDefault(); var otherTable = (from t in tables where t.ID == fk.OtherTableID select t).FirstOrDefault(); if (thisTable == null || otherTable == null) { continue; } var thisColumn = (from c in thisTable.Columns where c.ColumnName == fk.ThisColumn select c).Single(); var otherColumn = (from c in otherTable.Columns where c.ColumnName == fk.OtherColumn select c).Single(); var key = thisTable.ForeignKeys.FirstOrDefault(f => f.KeyName == fk.Name); if (key == null) { key = new ForeignKeySchema { KeyName = fk.Name, MemberName = fk.Name, ThisTable = thisTable, OtherTable = otherTable, ThisColumns = new List <ColumnSchema>(), OtherColumns = new List <ColumnSchema>(), CanBeNull = true, }; thisTable.ForeignKeys.Add(key); } key.ThisColumns.Add(thisColumn); key.OtherColumns.Add(otherColumn); } #endregion } else { tables = new List <TableSchema>(); } if (options.GetProcedures) { #region Procedures var sqlProvider = dataConnection.DataProvider.CreateSqlProvider(); var procs = GetProcedures(dataConnection); var procPparams = GetProcedureParameters(dataConnection); if (procs != null) { procedures = ( from sp in procs where (IncludedSchemas.Length == 0 || IncludedSchemas.Contains(sp.SchemaName)) && (ExcludedSchemas.Length == 0 || !ExcludedSchemas.Contains(sp.SchemaName)) join p in procPparams on sp.ProcedureID equals p.ProcedureID into gr select new ProcedureSchema { CatalogName = sp.CatalogName, SchemaName = sp.SchemaName, ProcedureName = sp.ProcedureName, MemberName = ToValidName(sp.ProcedureName), IsFunction = sp.IsFunction, IsTableFunction = sp.IsTableFunction, IsDefaultSchema = sp.IsDefaultSchema, Parameters = ( from pr in gr join dt in DataTypes on pr.DataType equals dt.TypeName into g1 from dt in g1.DefaultIfEmpty() let systemType = GetSystemType(pr.DataType, dt, pr.Length ?? 0, pr.Precision, pr.Scale) orderby pr.Ordinal select new ParameterSchema { SchemaName = pr.ParameterName, SchemaType = GetDbType(pr.DataType, dt, pr.Length ?? 0, pr.Precision, pr.Scale), IsIn = pr.IsIn, IsOut = pr.IsOut, IsResult = pr.IsResult, Size = pr.Length, ParameterName = ToValidName(pr.ParameterName), ParameterType = ToTypeName(systemType, true), SystemType = systemType ?? typeof(object), DataType = GetDataType(pr.DataType, null) } ).ToList() } into ps where ps.Parameters.All(p => p.SchemaType != "table type") select ps ).ToList(); var current = 1; foreach (var procedure in procedures) { if ((!procedure.IsFunction || procedure.IsTableFunction) && options.LoadProcedure(procedure)) { var commandText = sqlProvider.BuildTableName( new StringBuilder(), procedure.CatalogName, procedure.SchemaName, procedure.ProcedureName).ToString(); CommandType commandType; DataParameter[] parameters; if (procedure.IsTableFunction) { commandText = "SELECT * FROM " + commandText + "("; for (var i = 0; i < procedure.Parameters.Count; i++) { if (i != 0) { commandText += ","; } commandText += "NULL"; } commandText += ")"; commandType = CommandType.Text; parameters = new DataParameter[0]; } else { commandType = CommandType.StoredProcedure; parameters = procedure.Parameters.Select(p => new DataParameter { Name = p.ParameterName, Value = p.SystemType == typeof(string) ? "" : p.SystemType == typeof(DateTime) ? DateTime.Now : DefaultValue.GetValue(p.SystemType), DataType = p.DataType, Size = p.Size, Direction = p.IsIn ? p.IsOut ? ParameterDirection.InputOutput : ParameterDirection.Input : ParameterDirection.Output }).ToArray(); } { try { var st = GetProcedureSchema(dataConnection, commandText, commandType, parameters); if (st != null) { procedure.ResultTable = new TableSchema { IsProcedureResult = true, TypeName = ToValidName(procedure.ProcedureName + "Result"), ForeignKeys = new List <ForeignKeySchema>(), Columns = GetProcedureResultColumns(st) }; foreach (var column in procedure.ResultTable.Columns) { column.Table = procedure.ResultTable; } procedure.SimilarTables = ( from t in tables where t.Columns.Count == procedure.ResultTable.Columns.Count let zip = t.Columns.Zip(procedure.ResultTable.Columns, (c1, c2) => new { c1, c2 }) where zip.All(z => z.c1.ColumnName == z.c2.ColumnName && z.c1.SystemType == z.c2.SystemType) select t ).ToList(); } } catch (Exception ex) { procedure.ResultException = ex; } } } options.ProcedureLoadingProgress(procedures.Count, current++); } } else { procedures = new List <ProcedureSchema>(); } #endregion } else { procedures = new List <ProcedureSchema>(); } return(ProcessSchema(new DatabaseSchema { DataSource = GetDataSourceName(dbConnection), Database = GetDatabaseName(dbConnection), ServerVersion = dbConnection.ServerVersion, Tables = tables, Procedures = procedures, })); }