diff --git a/Extensions/FreeSql.Extensions.ZeroEntity/ZeroDbContext.cs b/Extensions/FreeSql.Extensions.ZeroEntity/ZeroDbContext.cs index abf35f95a..42b958f9a 100644 --- a/Extensions/FreeSql.Extensions.ZeroEntity/ZeroDbContext.cs +++ b/Extensions/FreeSql.Extensions.ZeroEntity/ZeroDbContext.cs @@ -132,7 +132,6 @@ ManyToMany 级联删除中间表(注意不删除外部根) _orm.CodeFirst.SyncStructure(table, table.DbName, false); } - static List ValidateSchemaToInfoInternal(IFreeSql orm, IEnumerable schemas) { var common = (orm.Ado as AdoProvider)._util; @@ -264,6 +263,48 @@ ManyToMany 级联删除中间表(注意不删除外部根) return tables; } + /// + /// 从数据库中加载 TableDescriptor 描述 + /// - 不支持 Navigates + /// - 不支持 Indexes IndexMethod + /// - 暂支持 SqlServer/MySql decimal(10,2)(其他数据库需实现对应 IDbFirst) + /// + static TableDescriptor LoadTableDescriptor(IFreeSql orm, string tableName) + { + var dbinfo = orm.DbFirst.GetTableByName(tableName, true); + if (dbinfo == null) throw new Exception($"表“{tableName}”不存在"); + var tb = new TableDescriptor + { + Comment = dbinfo.Comment, + DbName = dbinfo.Name, + Name = dbinfo.Name, + DisableSyncStructure = false, + }; + tb.Columns.AddRange(dbinfo.Columns.Select(a => new TableDescriptor.ColumnDescriptor + { + Name = a.Name, + DbType = a.DbTypeText, + IsPrimary = a.IsPrimary, + IsIdentity = a.IsIdentity, + IsNullable = a.IsNullable, + IsVersion = false, + MapType = a.CsType, + ServerTime = DateTimeKind.Unspecified, + InsertValueSql = a.DefaultValue, + StringLength = a.MaxLength, + Precision = a.Precision, + Scale = a.Scale, + Comment = a.Comment, + })); + tb.Indexes.AddRange(dbinfo.Indexes.Select(a => new TableDescriptor.IndexDescriptor + { + Name = a.Name, + IsUnique = a.IsUnique, + Fields = string.Join(",", a.Columns.Select(b => b.Column)), + })); + return tb; + } + public ZeroDbContext WithTransaction(DbTransaction value) { _transaction = value; diff --git a/FreeSql-ZeroEntity.sln b/FreeSql-ZeroEntity.sln index 9bd374259..836b4b971 100644 --- a/FreeSql-ZeroEntity.sln +++ b/FreeSql-ZeroEntity.sln @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.Sqlite", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero_entity", "Examples\zero_entity\zero_entity.csproj", "{97E60B48-06AC-42F3-90A8-DFC5FD386582}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Provider.Oracle", "Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj", "{3EDA83F1-0F47-D363-9FD7-6A68B81E93C8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,8 +35,15 @@ Global {97E60B48-06AC-42F3-90A8-DFC5FD386582}.Debug|Any CPU.Build.0 = Debug|Any CPU {97E60B48-06AC-42F3-90A8-DFC5FD386582}.Release|Any CPU.ActiveCfg = Release|Any CPU {97E60B48-06AC-42F3-90A8-DFC5FD386582}.Release|Any CPU.Build.0 = Release|Any CPU + {3EDA83F1-0F47-D363-9FD7-6A68B81E93C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EDA83F1-0F47-D363-9FD7-6A68B81E93C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EDA83F1-0F47-D363-9FD7-6A68B81E93C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EDA83F1-0F47-D363-9FD7-6A68B81E93C8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B7E48B6A-A1A8-477E-AC28-EFD2E83369EF} + EndGlobalSection EndGlobal diff --git a/FreeSql/DatabaseModel/DbColumnInfo.cs b/FreeSql/DatabaseModel/DbColumnInfo.cs index ffb297c6a..4be528b79 100644 --- a/FreeSql/DatabaseModel/DbColumnInfo.cs +++ b/FreeSql/DatabaseModel/DbColumnInfo.cs @@ -33,6 +33,14 @@ namespace FreeSql.DatabaseModel /// public int MaxLength { get; set; } /// + /// 暂支持 SqlServer/MySql(其他数据库待补充) + /// + public int Precision { get; set; } + /// + /// 暂支持 SqlServer/MySql(其他数据库待补充) + /// + public int Scale { get; set; } + /// /// 主键 /// public bool IsPrimary { get; set; } diff --git a/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlDbFirst.cs b/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlDbFirst.cs index 6d12fd986..50c4ab6e3 100644 --- a/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlDbFirst.cs +++ b/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlDbFirst.cs @@ -246,7 +246,9 @@ case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable', case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity', a.column_comment 'comment', a.column_default 'default_value', -a.ordinal_position +a.ordinal_position, +a.numeric_precision, +a.numeric_scale from information_schema.columns a where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseIn}) and {loc8} "; @@ -267,6 +269,8 @@ where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseI string comment = string.Concat(row[7]); string defaultValue = string.Concat(row[8]); var position = int.Parse(string.Concat(row[9])); + int.TryParse(string.Concat(row[10]), out var numeric_precision); + int.TryParse(string.Concat(row[11]), out var numeric_scale); if (max_length == 0) max_length = -1; if (database.Length == 1) @@ -285,7 +289,9 @@ where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseI Table = loc2[table_id], Comment = comment, DefaultValue = defaultValue, - Position = position + Position = position, + Precision = numeric_precision, + Scale = numeric_scale, }); loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]); loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]); diff --git a/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerDbFirst.cs b/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerDbFirst.cs index b21175aa6..e6ea21a2b 100644 --- a/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerDbFirst.cs +++ b/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerDbFirst.cs @@ -283,6 +283,9 @@ where {1} ,a.is_nullable 'isnullable' ,a.is_identity 'isidentity' ,f.text as 'defaultvalue' +,a.column_id as 'position' +,a.precision +,a.scale from sys.columns", loc8.ToString().Replace("a.table_name", "a.object_id"), @" left join syscomments f on f.id = a.default_object_id "); @@ -295,13 +298,15 @@ left join syscomments f on f.id = a.default_object_id ,cast(0 as bit) 'isnullable' ,a.is_output 'isidentity' ,'' as 'defaultvalue' +,1 as 'position' +,a.precision +,a.scale from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), ""); } sql = $"use [{db}];{sql};use [{olddatabase}]; "; ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); if (ds == null) return loc1; - var position = 0; foreach (object[] row in ds) { var table_id = string.Concat(row[0]); @@ -314,7 +319,10 @@ from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), " var is_nullable = bool.Parse(string.Concat(row[7])); var is_identity = bool.Parse(string.Concat(row[8])); var defaultValue = string.Concat(row[9]); + var position = int.Parse(string.Concat(row[10])); if (max_length == 0) max_length = -1; + int.TryParse(string.Concat(row[11]), out var numeric_precision); + int.TryParse(string.Concat(row[12]), out var numeric_scale); loc3[object_id].Add(column, new DbColumnInfo { @@ -328,7 +336,9 @@ from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), " Table = loc2[object_id], Comment = comment, DefaultValue = defaultValue, - Position = ++position + Position = position, + Precision = numeric_precision, + Scale = numeric_scale, }); loc3[object_id][column].DbType = this.GetDbType(loc3[object_id][column]); loc3[object_id][column].CsType = this.GetCsTypeInfo(loc3[object_id][column]); diff --git a/Providers/FreeSql.Provider.MySql/MySqlDbFirst.cs b/Providers/FreeSql.Provider.MySql/MySqlDbFirst.cs index 0de90a3dd..949436fed 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlDbFirst.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlDbFirst.cs @@ -279,7 +279,9 @@ case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable', case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity', a.column_comment 'comment', a.column_default 'default_value', -a.ordinal_position +a.ordinal_position, +a.numeric_precision, +a.numeric_scale from information_schema.columns a where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseIn}) and {loc8} "; @@ -300,6 +302,8 @@ where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseI string comment = string.Concat(row[7]); string defaultValue = string.Concat(row[8]); var position = int.Parse(string.Concat(row[9])); + int.TryParse(string.Concat(row[10]), out var numeric_precision); + int.TryParse(string.Concat(row[11]), out var numeric_scale); if (max_length == 0) max_length = -1; if (database.Length == 1) @@ -318,7 +322,9 @@ where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseI Table = loc2[table_id], Comment = comment, DefaultValue = defaultValue, - Position = position + Position = position, + Precision = numeric_precision, + Scale = numeric_scale, }); loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]); loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]); diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlDbFirst.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlDbFirst.cs index 1993f4283..49b4428ad 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlDbFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlDbFirst.cs @@ -245,7 +245,9 @@ case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable', case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity', a.column_comment 'comment', a.column_default 'default_value', -a.ordinal_position +a.ordinal_position, +a.numeric_precision, +a.numeric_scale from information_schema.columns a where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseIn}) and {loc8} "; @@ -266,6 +268,8 @@ where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseI string comment = string.Concat(row[7]); string defaultValue = string.Concat(row[8]); var position = int.Parse(string.Concat(row[9])); + int.TryParse(string.Concat(row[10]), out var numeric_precision); + int.TryParse(string.Concat(row[11]), out var numeric_scale); if (max_length == 0) max_length = -1; if (database.Length == 1) @@ -284,7 +288,9 @@ where {(ignoreCase ? "lower(a.table_schema)" : "a.table_schema")} in ({databaseI Table = loc2[table_id], Comment = comment, DefaultValue = defaultValue, - Position = position + Position = position, + Position = position, + Precision = numeric_precision, }); loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]); loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerDbFirst.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerDbFirst.cs index e9f7a1d4e..ad814a6ba 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerDbFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerDbFirst.cs @@ -286,6 +286,9 @@ where {1} ,a.is_nullable 'isnullable' ,a.is_identity 'isidentity' ,f.text as 'defaultvalue' +,a.column_id as 'position' +,a.precision +,a.scale from sys.columns", loc8.ToString().Replace("a.table_name", "a.object_id"), @" left join syscomments f on f.id = a.default_object_id "); @@ -298,13 +301,15 @@ left join syscomments f on f.id = a.default_object_id ,cast(0 as bit) 'isnullable' ,a.is_output 'isidentity' ,'' as 'defaultvalue' +,1 as 'position' +,a.precision +,a.scale from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), ""); } sql = $"use [{db}];{sql};use [{olddatabase}]; "; ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); if (ds == null) return loc1; - var position = 0; foreach (object[] row in ds) { var table_id = string.Concat(row[0]); @@ -317,7 +322,10 @@ from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), " var is_nullable = bool.Parse(string.Concat(row[7])); var is_identity = bool.Parse(string.Concat(row[8])); var defaultValue = string.Concat(row[9]); + var position = int.Parse(string.Concat(row[10])); if (max_length == 0) max_length = -1; + int.TryParse(string.Concat(row[11]), out var numeric_precision); + int.TryParse(string.Concat(row[12]), out var numeric_scale); loc3[object_id].Add(column, new DbColumnInfo { @@ -331,7 +339,9 @@ from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), " Table = loc2[object_id], Comment = comment, DefaultValue = defaultValue, - Position = ++position + Position = position, + Precision = numeric_precision, + Scale = numeric_scale, }); loc3[object_id][column].DbType = this.GetDbType(loc3[object_id][column]); loc3[object_id][column].CsType = this.GetCsTypeInfo(loc3[object_id][column]); diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerDbFirst.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerDbFirst.cs index eab58d30b..2d477ab3e 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerDbFirst.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerDbFirst.cs @@ -290,6 +290,8 @@ where {1} ,a.is_identity 'isidentity' ,f.text as 'defaultvalue' ,a.column_id as 'position' +,a.precision +,a.scale from sys.columns", loc8.ToString().Replace("a.table_name", "a.object_id"), @" left join syscomments f on f.id = a.default_object_id "); @@ -303,6 +305,8 @@ left join syscomments f on f.id = a.default_object_id ,a.is_output 'isidentity' ,'' as 'defaultvalue' ,1 as 'position' +,a.precision +,a.scale from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), ""); } sql = $"use [{db}];{sql};use [{olddatabase}]; "; @@ -323,6 +327,8 @@ from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), " var defaultValue = string.Concat(row[9]); var position = int.Parse(string.Concat(row[10])); if (max_length == 0) max_length = -1; + int.TryParse(string.Concat(row[11]), out var numeric_precision); + int.TryParse(string.Concat(row[12]), out var numeric_scale); loc3[object_id].Add(column, new DbColumnInfo { @@ -336,7 +342,9 @@ from sys.parameters", loc88.ToString().Replace("a.table_name", "a.object_id"), " Table = loc2[object_id], Comment = comment, DefaultValue = defaultValue, - Position = position + Position = position, + Precision = numeric_precision, + Scale = numeric_scale, }); loc3[object_id][column].DbType = this.GetDbType(loc3[object_id][column]); loc3[object_id][column].CsType = this.GetCsTypeInfo(loc3[object_id][column]);