diff --git a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj index 80f24053..60966e88 100644 --- a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj +++ b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql 扩展包,可实现【延时加载】属性. diff --git a/FreeSql.Tests/FreeSql.Tests.xml b/FreeSql.Tests/FreeSql.Tests.xml index 55568931..6b525395 100644 --- a/FreeSql.Tests/FreeSql.Tests.xml +++ b/FreeSql.Tests/FreeSql.Tests.xml @@ -74,9 +74,9 @@ - + - 主键,ID + 测试中文重命名id diff --git a/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/UnitTest1.cs index 54d3e0d6..6234d919 100644 --- a/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/UnitTest1.cs @@ -232,14 +232,13 @@ namespace FreeSql.Tests { } public class Templates { /// - /// 主键,ID + /// 测试中文重命名id /// - [Column(IsPrimary = true)] - public Guid Id { get; set; } + [Column(IsPrimary = true, OldName = "Id")] + public Guid Id2 { get; set; } public string Title { get; set; } public DateTime AddTime { get; set; } = DateTime.Now; public DateTime EditTime { get; set; } - [Column(DbType = "text")] public string Code { get; set; } } public class TaskBuild { @@ -270,20 +269,20 @@ namespace FreeSql.Tests { [Fact] public void Test1() { - var dkdkdkd = g.mysql.Select().ToList(); + var dkdkdkd = g.oracle.Select().ToList(); - var testaddlist = new List(); - for(var a = 0; a < 133905; a++) { - testaddlist.Add(new NewsArticle { - ArticleTitle = "testaddlist_topic" + a, - Hits = a, - }); - } - g.sqlite.Insert(testaddlist) - //.NoneParameter() - .ExecuteAffrows(); + //var testaddlist = new List(); + //for(var a = 0; a < 133905; a++) { + // testaddlist.Add(new NewsArticle { + // ArticleTitle = "testaddlist_topic" + a, + // Hits = a, + // }); + //} + //g.sqlite.Insert(testaddlist) + // //.NoneParameter() + // .ExecuteAffrows(); g.mysql.Aop.ParseExpression = (s, e) => { diff --git a/FreeSql.Tests/g.cs b/FreeSql.Tests/g.cs index 6df85b6c..7396b139 100644 --- a/FreeSql.Tests/g.cs +++ b/FreeSql.Tests/g.cs @@ -39,6 +39,20 @@ public class g { }); public static IFreeSql pgsql => pgsqlLazy.Value; + static Lazy sqlserverLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=10") + .UseAutoSyncStructure(true) + .UseMonitorCommand( + cmd => { + Trace.WriteLine(cmd.CommandText); + }, //监听SQL命令对象,在执行前 + (cmd, traceLog) => { + Console.WriteLine(traceLog); + }) //监听SQL命令对象,在执行后 + .UseLazyLoading(true) + .Build()); + public static IFreeSql sqlserver => sqlserverLazy.Value; + static Lazy oracleLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=10") .UseAutoSyncStructure(true) diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index cd3eb7be..37ca9137 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite. diff --git a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj index 348ebb56..e27094b4 100644 --- a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj +++ b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj @@ -2,7 +2,7 @@ netstandard2.0;net452 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql 数据库实现,基于 MySql 5.6 diff --git a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs index 1c9950c8..8fed3c85 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs @@ -152,7 +152,8 @@ select a.column_name, a.column_type, 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' +case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity', +a.column_comment 'comment' from information_schema.columns a where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); @@ -164,7 +165,8 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); sqlType = a1, is_nullable = string.Concat(a[2]) == "1", is_identity = string.Concat(a[3]) == "1", - is_unsigned = string.Concat(a[1]).EndsWith(" unsigned") + is_unsigned = string.Concat(a[1]).EndsWith(" unsigned"), + comment = string.Concat(a[4]) }; }, StringComparer.CurrentCultureIgnoreCase); @@ -174,18 +176,22 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); var isIdentityChanged = tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1; if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { + var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? ""); if ((tbcol.Attribute.DbType.IndexOf(" unsigned", StringComparison.CurrentCultureIgnoreCase) != -1) != tbstructcol.is_unsigned || tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false || tbcol.Attribute.IsNullable != tbstructcol.is_nullable || - tbcol.Attribute.IsIdentity != tbstructcol.is_identity) { + tbcol.Attribute.IsIdentity != tbstructcol.is_identity || + isCommentChanged) { sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.DbType); + if (isCommentChanged) sbalter.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "")); if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(")"); sbalter.Append(";\r\n"); } - if (tbstructcol.column == tbcol.Attribute.OldName) { + if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0) { //修改列名 - sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType); - if (isIdentityChanged) sb.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")"); + sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType); + if (isCommentChanged) sbalter.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "")); + if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")"); sbalter.Append(";\r\n"); } continue; @@ -193,6 +199,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); //添加列 sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType); if (tbcol.Attribute.IsNullable == false) sbalter.Append(" DEFAULT ").Append(_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)); + if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "")); if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")"); sbalter.Append(";\r\n"); } @@ -228,6 +235,7 @@ where a.constraint_schema IN ({0}) and a.table_name IN ({1})", tboldname ?? tbna sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" "); sb.Append(tbcol.Attribute.DbType); if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT"); + if (string.IsNullOrEmpty(tbcol.Comment) == false) sb.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)); sb.Append(","); } if (tb.Primarys.Any()) { diff --git a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj index 667ae1e4..5c4526ac 100644 --- a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj +++ b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql 数据库实现,基于 MySql 5.6 diff --git a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj index 9b5064d8..d3155615 100644 --- a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj +++ b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql 数据库实现,基于 Oracle 11 diff --git a/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs b/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs index 6893b677..7d59e1c1 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs @@ -112,6 +112,11 @@ namespace FreeSql.Oracle { } sb.Remove(sb.Length - 1, 1); sb.Append("\r\n) \r\nLOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n';\r\n"); + //备注 + foreach (var tbcol in tb.Columns.Values) { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + sb.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment).Replace("'", "''")).Append("';\r\n"); + } continue; } //如果新表,旧表在一个模式下,直接修改表名 @@ -127,17 +132,19 @@ namespace FreeSql.Oracle { //对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段 var sql = _commonUtils.FormatSql($@" select -column_name, -data_type, -data_length, -data_precision, -data_scale, -char_used, -case when nullable = 'Y' then 1 else 0 end, -nvl((select 1 from user_sequences where sequence_name='{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||all_tab_columns.column_name), 0), -nvl((select 1 from user_triggers where trigger_name='{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||all_tab_columns.column_name||'TI'), 0) -from all_tab_columns -where owner={{0}} and table_name={{1}}", tboldname ?? tbname); +a.column_name, +a.data_type, +a.data_length, +a.data_precision, +a.data_scale, +a.char_used, +case when a.nullable = 'Y' then 1 else 0 end, +nvl((select 1 from user_sequences where sequence_name='{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||a.column_name), 0), +nvl((select 1 from user_triggers where trigger_name='{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||a.column_name||'TI'), 0), +b.comments +from all_tab_columns a +left join all_col_comments b on b.owner = a.owner and b.table_name = a.table_name and b.column_name = a.column_name +where a.owner={{0}} and a.table_name={{1}}", tboldname ?? tbname); var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => { var sqlType = GetOracleSqlTypeFullName(a); @@ -145,7 +152,8 @@ where owner={{0}} and table_name={{1}}", tboldname ?? tbname); column = string.Concat(a[0]), sqlType, is_nullable = string.Concat(a[6]) == "1", - is_identity = string.Concat(a[7]) == "1" && string.Concat(a[8]) == "1" + is_identity = string.Concat(a[7]) == "1" && string.Concat(a[8]) == "1", + comment = string.Concat(a[9]) }; }, StringComparer.CurrentCultureIgnoreCase); @@ -153,7 +161,8 @@ where owner={{0}} and table_name={{1}}", tboldname ?? tbname); foreach (var tbcol in tb.Columns.Values) { var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"NOT\s+NULL", "NULL"); if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || - string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { + string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { + var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? ""); if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) istmpatler = true; //sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY (").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(dbtypeNoneNotNull).Append(")';\r\n"); @@ -164,9 +173,11 @@ where owner={{0}} and table_name={{1}}", tboldname ?? tbname); } if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true)); - if (tbstructcol.column == tbcol.Attribute.OldName) + if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0) //修改列名 - sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append("';\r\n"); + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append("';\r\n"); + if (isCommentChanged) + sbalter.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "").Replace("'", "''")).Append("';\r\n"); continue; } //添加列 @@ -176,6 +187,7 @@ where owner={{0}} and table_name={{1}}", tboldname ?? tbname); sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" NOT NULL';\r\n"); } if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true)); + if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "").Replace("'", "''")).Append("';\r\n"); } var dsuksql = _commonUtils.FormatSql(@" select @@ -231,6 +243,11 @@ and a.owner in ({0}) and a.table_name in ({1})", tboldname ?? tbname); } sb.Remove(sb.Length - 1, 1); sb.Append("\r\n) LOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n';\r\n"); + //备注 + foreach (var tbcol in tb.Columns.Values) { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + sb.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.FTmp_{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment).Replace("'", "''")).Append("';\r\n"); + } sb.Append("execute immediate 'INSERT INTO ").Append(tmptablename).Append(" ("); foreach (var tbcol in tb.Columns.Values) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); diff --git a/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs b/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs index 087580ad..4d008622 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs @@ -199,7 +199,7 @@ a.data_length, a.data_precision, a.data_scale, a.char_used, -case when nullable = 'Y' then 1 else 0 end, +case when a.nullable = 'Y' then 1 else 0 end, nvl((select 1 from user_sequences where upper(sequence_name)=upper(a.table_name||'_seq_'||a.column_name)), 0), b.comments from all_tab_cols a diff --git a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj index e2ff1e19..d9e23606 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj +++ b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql 数据库实现,基于 PostgreSQL 9.5 diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs index 4568a53f..708f73a3 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs @@ -155,6 +155,11 @@ namespace FreeSql.PostgreSQL { } sb.Remove(sb.Length - 1, 1); sb.Append("\r\n) WITH (OIDS=FALSE);\r\n"); + //备注 + foreach (var tbcol in tb.Columns.Values) { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + sb.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)).Append(";\r\n"); + } continue; } //如果新表,旧表在一个数据库和模式下,直接修改表名 @@ -176,7 +181,8 @@ case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.at case when t.typelem > 0 and t.typinput::varchar = 'array_in' then t2.typname else t.typname end, case when a.attnotnull then '0' else '1' end as is_nullable, e.adsrc, -a.attndims +a.attndims, +d.description as comment from pg_class c inner join pg_attribute a on a.attnum > 0 and a.attrelid = c.oid inner join pg_type t on t.oid = a.atttypid @@ -207,7 +213,8 @@ where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname); max_length = long.Parse(string.Concat(a[2])), is_nullable = string.Concat(a[4]) == "1", is_identity = string.Concat(a[5]).StartsWith(@"nextval('") && string.Concat(a[5]).EndsWith(@"'::regclass)"), - attndims + attndims, + comment = string.Concat(a[7]) }; }, StringComparer.CurrentCultureIgnoreCase); @@ -215,6 +222,7 @@ where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname); foreach (var tbcol in tb.Columns.Values) { if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { + var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? ""); if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false || tbcol.Attribute.DbType.Contains("[]") != (tbstructcol.attndims > 0)) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TYPE ").Append(tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n"); @@ -222,9 +230,11 @@ where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname); sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable == true ? "DROP" : "SET").Append(" NOT NULL;\r\n"); if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true)); - if (tbstructcol.column == tbcol.Attribute.OldName) + if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0) //修改列名 - sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n"); + sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n"); + if (isCommentChanged) + sbalter.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)).Append(";\r\n"); continue; } //添加列 @@ -232,6 +242,7 @@ where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname); sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" = ").Append(_commonUtils.FormatSql("{0};\r\n", tbcol.Attribute.DbDefautValue)); if (tbcol.Attribute.IsNullable == false) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" SET NOT NULL;\r\n"); if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true)); + if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)).Append(";\r\n"); } var dsuksql = _commonUtils.FormatSql(@" select @@ -288,6 +299,11 @@ where pg_namespace.nspname={0} and pg_class.relname={1} and pg_constraint.contyp } sb.Remove(sb.Length - 1, 1); sb.Append("\r\n) WITH (OIDS=FALSE);\r\n"); + //备注 + foreach (var tbcol in tb.Columns.Values) { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + sb.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.FreeSqlTmp_{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)).Append(";\r\n"); + } sb.Append("INSERT INTO ").Append(tmptablename).Append(" ("); foreach (var tbcol in tb.Columns.Values) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); diff --git a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj index 0546a070..6a700bf8 100644 --- a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj +++ b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj @@ -2,7 +2,7 @@ netstandard2.0;net451 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql 数据库实现,基于 SqlServer 2005+,并根据版本适配分页方法:row_number 或 offset fetch next diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs index 1356b66f..6df8fd72 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs @@ -63,7 +63,37 @@ namespace FreeSql.SqlServer { } return null; } - + + void AddOrUpdateMS_Description(StringBuilder sb, string schema, string table, string column, string comment) { + if (string.IsNullOrEmpty(comment)) { + sb.AppendFormat(@" +IF ((SELECT COUNT(1) from fn_listextendedproperty('MS_Description', + 'SCHEMA', N'{0}', + 'TABLE', N'{1}', + 'COLUMN', N'{2}')) > 0) + EXEC sp_dropextendedproperty @name = N'MS_Description' + , @level0type = 'SCHEMA', @level0name = N'{0}' + , @level1type = 'TABLE', @level1name = N'{1}' + , @level2type = 'COLUMN', @level2name = N'{2}' +", schema.Replace("'", "''"), table.Replace("'", "''"), column.Replace("'", "''")); + return; + } + sb.AppendFormat(@" +IF ((SELECT COUNT(1) from fn_listextendedproperty('MS_Description', + 'SCHEMA', N'{0}', + 'TABLE', N'{1}', + 'COLUMN', N'{2}')) > 0) + EXEC sp_updateextendedproperty @name = N'MS_Description', @value = N'{3}' + , @level0type = 'SCHEMA', @level0name = N'{0}' + , @level1type = 'TABLE', @level1name = N'{1}' + , @level2type = 'COLUMN', @level2name = N'{2}' +ELSE + EXEC sp_addextendedproperty @name = N'MS_Description', @value = N'{3}' + , @level0type = 'SCHEMA', @level0name = N'{0}' + , @level1type = 'TABLE', @level1name = N'{1}' + , @level2type = 'COLUMN', @level2name = N'{2}' +", schema.Replace("'", "''"), table.Replace("'", "''"), column.Replace("'", "''"), comment?.Replace("'", "''") ?? ""); + } public override string GetComparisonDDLStatements(params Type[] entityTypes) { var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); var database = conn.Value.Database; @@ -133,6 +163,11 @@ namespace FreeSql.SqlServer { sb.Remove(sb.Length - 2, 2).Append("),"); } sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n"); + //备注 + foreach (var tbcol in tb.Columns.Values) { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + AddOrUpdateMS_Description(sb, tbname[1], tbname[2], tbcol.Attribute.Name, tbcol.Comment); + } continue; } //如果新表,旧表在一个数据库和模式下,直接修改表名 @@ -160,6 +195,7 @@ a.name 'Column' else '' end as 'SqlType' ,case when a.is_nullable = 1 then '1' else '0' end 'IsNullable' ,case when a.is_identity = 1 then '1' else '0' end 'IsIdentity' +,c.value from sys.columns a inner join sys.types b on b.user_type_id = a.user_type_id left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = a.column_id @@ -172,23 +208,27 @@ use " + database, tboldname ?? tbname); column = string.Concat(a[0]), sqlType = string.Concat(a[1]), is_nullable = string.Concat(a[2]) == "1", - is_identity = string.Concat(a[3]) == "1" + is_identity = string.Concat(a[3]) == "1", + comment = string.Concat(a[4]) }, StringComparer.CurrentCultureIgnoreCase); if (istmpatler == false) { foreach (var tbcol in tb.Columns.Values) { if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) { + var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? ""); if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false || tbcol.Attribute.IsNullable != tbstructcol.is_nullable || tbcol.Attribute.IsIdentity != tbstructcol.is_identity) { istmpatler = true; break; } - if (tbstructcol.column == tbcol.Attribute.OldName) { + if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0) //修改列名 - sbalter.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1}, 'COLUMN';\r\n", $"{tbname[0]}.{tbname[1]}.{tbname[2]}.{tbcol.Attribute.OldName}", tbcol.Attribute.Name)); - } + sbalter.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1}, 'COLUMN';\r\n", $"{tbname[0]}.{tbname[1]}.{tbname[2]}.{tbstructcol.column}", tbcol.Attribute.Name)); + if (isCommentChanged) + //修改备备注 + AddOrUpdateMS_Description(sbalter, tbname[1], tbname[2], tbcol.Attribute.Name, tbcol.Comment); continue; } //添加列 @@ -199,6 +239,7 @@ use " + database, tboldname ?? tbname); if (addcoldbdefault != null) sbalter.Append(_commonUtils.FormatSql(" default({0})", addcoldbdefault)); } sbalter.Append(";\r\n"); + if (string.IsNullOrEmpty(tbcol.Comment) == false) AddOrUpdateMS_Description(sbalter, tbname[1], tbname[2], tbcol.Attribute.Name, tbcol.Comment); } var dsuksql = string.Format(@" use [{0}]; @@ -265,6 +306,11 @@ use " + database, tboldname ?? tbname); sb.Remove(sb.Length - 2, 2).Append("),"); } sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n"); + //备注 + foreach (var tbcol in tb.Columns.Values) { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + AddOrUpdateMS_Description(sb, tbname[1], $"FreeSqlTmp_{tbname[2]}", tbcol.Attribute.Name, tbcol.Comment); + } sb.Append("ALTER TABLE ").Append(tmptablename).Append(" SET (LOCK_ESCALATION = TABLE);\r\n"); if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" ON;\r\n"); sb.Append("IF EXISTS(SELECT 1 FROM ").Append(tablename).Append(")\r\n"); diff --git a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj index a53f4f70..8bc42afb 100644 --- a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj +++ b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.10 + 0.6.11 true YeXiangQin FreeSql 数据库实现,基于 Sqlite 3.0 diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs b/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs index e3fdc8c5..e3488b89 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs @@ -152,7 +152,7 @@ namespace FreeSql.Sqlite { istmpatler = true; if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) istmpatler = true; - if (tbstructcol.column == tbcol.Attribute.OldName) + if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0) //修改列名 istmpatler = true; continue;