From f2f1495efc2f55871283b2a4d648fedc2dc2996a Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Tue, 21 Jul 2020 15:22:33 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20IInsert/IUpdate=20Batc?= =?UTF-8?q?hProgress=20=E6=96=B9=E6=B3=95=E5=A4=84=E7=90=86=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=8F=92=E5=85=A5/=E6=9B=B4=E6=96=B0=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E8=BF=9B=E5=BA=A6=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.Tests/FreeSql.Tests/UnitTest3.cs | 6 +- FreeSql/FreeSql.xml | 164 +++++++++++------- FreeSql/Interface/Curd/IInsert.cs | 14 +- FreeSql/Interface/Curd/IUpdate.cs | 14 +- .../Internal/CommonProvider/InsertProvider.cs | 17 ++ .../Internal/CommonProvider/UpdateProvider.cs | 13 ++ .../Internal/Model/BatchProgressEventArgs.cs | 32 ++++ .../FreeSql.Provider.MySql/MySqlCodeFirst.cs | 60 ++++--- .../MySql/OdbcMySqlCodeFirst.cs | 60 ++++--- .../SqlServer/OdbcSqlServerCodeFirst.cs | 59 ++++--- .../SqlServerCodeFirst.cs | 59 ++++--- 11 files changed, 325 insertions(+), 173 deletions(-) create mode 100644 FreeSql/Internal/Model/BatchProgressEventArgs.cs diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs index 44d9bd13..5125fee2 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs @@ -433,8 +433,12 @@ namespace FreeSql.Tests new SendInfo{ Code = "002", Binary = Encoding.UTF8.GetBytes("我是地球人") }, new SendInfo{ Code = "003", Binary = Encoding.UTF8.GetBytes("我是.net")}, new SendInfo{ Code = "004", Binary = Encoding.UTF8.GetBytes("我是freesql") }, + new SendInfo{ Code = "005", Binary = Encoding.UTF8.GetBytes("我是freesql233") }, }) - .NoneParameter().ExecuteAffrows(); + .NoneParameter() + .BatchOptions(3, 200) + .BatchProgress(a => Trace.WriteLine($"{a.Current}/{a.Total}")) + .ExecuteAffrows(); var slslsl = g.oracle.Select().ToList(); diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 6a822109..dc3e9926 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1069,11 +1069,18 @@ Sqlite 5000 999 若没有事务传入,内部(默认)会自动开启新事务,保证拆包执行的完整性。 - 指定根据 values 数量拆分执行 - 指定根据 parameters 数量拆分执行 + 指定根据 values 上限数量拆分执行 + 指定根据 parameters 上限数量拆分执行 是否自动开启事务 + + + 批量执行时,分批次执行的进度状态 + + 批量执行时的回调委托 + + 设置表名规则,可用于分库/分表,参数1:默认表名;返回值:新表名; @@ -2142,11 +2149,18 @@ Sqlite 200 999 若没有事务传入,内部(默认)会自动开启新事务,保证拆包执行的完整性。 - 指定根据 rows 数量拆分执行 - 指定根据 parameters 数量拆分执行 + 指定根据 rows 上限数量拆分执行 + 指定根据 parameters 上限数量拆分执行 是否自动开启事务 + + + 批量执行时,分批次执行的进度状态 + + 批量执行时的回调委托 + + 更新数据,设置更新的实体 @@ -2919,89 +2933,104 @@ 转大写同步结构,适用 Oracle/达梦/人大金仓 - - - 将数据库的主键、自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。 - 本功能会影响 IFreeSql 首次访问的速度。 - 若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除 + - - 不使用命令参数化执行,针对 Insert/Update - - - - - 是否生成命令参数化执行,针对 lambda 表达式解析 - 注意:常量不会参数化,变量才会做参数化 - var id = 100; - fsql.Select<T>().Where(a => a.id == id) 会参数化 - fsql.Select<T>().Where(a => a.id == 100) 不会参数化 - - - - - 延时加载导航属性对象,导航属性需要声明 virtual - - - - - 将实体类型与数据库对比,返回DDL语句 - - + - + - 将实体类型集合与数据库对比,返回DDL语句 + 获取c#类型对象 - 实体类型 + - + - 将实体类型与数据库对比,返回DDL语句(指定表名) + 获取ado.net读取方法, GetBoolean、GetInt64 - 实体类型 - 指定表名对比 + - + - 同步实体类型到数据库 - 注意:生产环境中谨慎使用 + 序列化 - + + - + - 同步实体类型集合到数据库 - 注意:生产环境中谨慎使用 + 反序列化 - + + - + - 同步实体类型到数据库(指定表名) - 注意:生产环境中谨慎使用 + 获取数据库枚举类型,适用 PostgreSQL - 实体类型 - 指定表名对比 + + - + - 根据 System.Type 获取数据库信息 + 如果实体类有自增属性,分成两个 List,有值的Item1 merge,无值的Item2 insert + + + + + + + AsType, Ctor, ClearData 三处地方需要重新加载 + + + + + AsType, Ctor, ClearData 三处地方需要重新加载 + + + + + 动态读取 DescriptionAttribute 注释文本 - + - FreeSql FluentApi 配置实体,方法名与特性相同 + 通过属性的注释文本,通过 xml 读取 - - + + Dict:key=属性名,value=注释 + + + + 创建一个过滤器 + + + 名字 + 表达式 + + + + + 当前操作的数据 + + + + + 当前批次 + + + + + 总批次数量 + + + + + me="entity"> @@ -3142,6 +3171,21 @@ 表达式 + + + 当前操作的数据 + + + + + 当前批次 + + + + + 总批次数量 + + 动态过滤条件 diff --git a/FreeSql/Interface/Curd/IInsert.cs b/FreeSql/Interface/Curd/IInsert.cs index 025f875b..739c046d 100644 --- a/FreeSql/Interface/Curd/IInsert.cs +++ b/FreeSql/Interface/Curd/IInsert.cs @@ -1,4 +1,5 @@ -using System; +using FreeSql.Internal.Model; +using System; using System.Collections.Generic; using System.Data; using System.Data.Common; @@ -91,12 +92,19 @@ namespace FreeSql /// Sqlite 5000 999 /// 若没有事务传入,内部(默认)会自动开启新事务,保证拆包执行的完整性。 /// - /// 指定根据 values 数量拆分执行 - /// 指定根据 parameters 数量拆分执行 + /// 指定根据 values 上限数量拆分执行 + /// 指定根据 parameters 上限数量拆分执行 /// 是否自动开启事务 /// IInsert BatchOptions(int valuesLimit, int parameterLimit, bool autoTransaction = true); + /// + /// 批量执行时,分批次执行的进度状态 + /// + /// 批量执行时的回调委托 + /// + IInsert BatchProgress(Action> callback); + /// /// 设置表名规则,可用于分库/分表,参数1:默认表名;返回值:新表名; /// diff --git a/FreeSql/Interface/Curd/IUpdate.cs b/FreeSql/Interface/Curd/IUpdate.cs index cc28b273..c2fd0b2b 100644 --- a/FreeSql/Interface/Curd/IUpdate.cs +++ b/FreeSql/Interface/Curd/IUpdate.cs @@ -1,4 +1,5 @@ -using System; +using FreeSql.Internal.Model; +using System; using System.Collections.Generic; using System.Data.Common; using System.Linq.Expressions; @@ -39,12 +40,19 @@ namespace FreeSql /// Sqlite 200 999 /// 若没有事务传入,内部(默认)会自动开启新事务,保证拆包执行的完整性。 /// - /// 指定根据 rows 数量拆分执行 - /// 指定根据 parameters 数量拆分执行 + /// 指定根据 rows 上限数量拆分执行 + /// 指定根据 parameters 上限数量拆分执行 /// 是否自动开启事务 /// IUpdate BatchOptions(int rowsLimit, int parameterLimit, bool autoTransaction = true); + /// + /// 批量执行时,分批次执行的进度状态 + /// + /// 批量执行时的回调委托 + /// + IUpdate BatchProgress(Action> callback); + /// /// 更新数据,设置更新的实体 /// diff --git a/FreeSql/Internal/CommonProvider/InsertProvider.cs b/FreeSql/Internal/CommonProvider/InsertProvider.cs index 281837e2..d60bfa2a 100644 --- a/FreeSql/Internal/CommonProvider/InsertProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertProvider.cs @@ -26,6 +26,7 @@ namespace FreeSql.Internal.CommonProvider public bool _noneParameter, _insertIdentity; public int _batchValuesLimit, _batchParameterLimit; public bool _batchAutoTransaction = true; + public Action> _batchProgress; public DbParameter[] _params; public DbTransaction _transaction; public DbConnection _connection; @@ -55,6 +56,7 @@ namespace FreeSql.Internal.CommonProvider { _batchValuesLimit = _batchParameterLimit = 0; _batchAutoTransaction = true; + _batchProgress = null; _insertIdentity = false; _source.Clear(); _ignore.Clear(); @@ -96,6 +98,12 @@ namespace FreeSql.Internal.CommonProvider return this; } + public IInsert BatchProgress(Action> callback) + { + _batchProgress = callback; + return this; + } + public IInsert AppendData(T1 source) { if (source != null) @@ -204,6 +212,7 @@ namespace FreeSql.Internal.CommonProvider } if (ss.Length == 1) { + _batchProgress?.Invoke(new BatchProgressStatus(_source, 1, 1)); ret = this.RawExecuteAffrows(); ClearData(); return ret; @@ -221,6 +230,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret += this.RawExecuteAffrows(); } } @@ -236,6 +246,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret += this.RawExecuteAffrows(); } _transaction.Commit(); @@ -276,6 +287,7 @@ namespace FreeSql.Internal.CommonProvider } if (ss.Length == 1) { + _batchProgress?.Invoke(new BatchProgressStatus(_source, 1, 1)); ret = this.RawExecuteIdentity(); ClearData(); return ret; @@ -293,6 +305,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); if (a < ss.Length - 1) this.RawExecuteAffrows(); else ret = this.RawExecuteIdentity(); } @@ -309,6 +322,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); if (a < ss.Length - 1) this.RawExecuteAffrows(); else ret = this.RawExecuteIdentity(); } @@ -350,6 +364,7 @@ namespace FreeSql.Internal.CommonProvider } if (ss.Length == 1) { + _batchProgress?.Invoke(new BatchProgressStatus(_source, 1, 1)); ret = this.RawExecuteInserted(); ClearData(); return ret; @@ -367,6 +382,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret.AddRange(this.RawExecuteInserted()); } } @@ -382,6 +398,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret.AddRange(this.RawExecuteInserted()); } _transaction.Commit(); diff --git a/FreeSql/Internal/CommonProvider/UpdateProvider.cs b/FreeSql/Internal/CommonProvider/UpdateProvider.cs index 39e62aa4..8fbf566f 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProvider.cs @@ -32,6 +32,7 @@ namespace FreeSql.Internal.CommonProvider public bool _noneParameter; public int _batchRowsLimit, _batchParameterLimit; public bool _batchAutoTransaction = true; + public Action> _batchProgress; public DbTransaction _transaction; public DbConnection _connection; @@ -101,6 +102,12 @@ namespace FreeSql.Internal.CommonProvider return this; } + public IUpdate BatchProgress(Action> callback) + { + _batchProgress = callback; + return this; + } + protected void ValidateVersionAndThrow(int affrows) { if (_table.VersionColumn != null && _source.Count > 0) @@ -144,6 +151,7 @@ namespace FreeSql.Internal.CommonProvider var ret = 0; if (ss.Length <= 1) { + if (_source?.Any() == true) _batchProgress?.Invoke(new BatchProgressStatus(_source, 1, 1)); ret = this.RawExecuteAffrows(); ClearData(); return ret; @@ -161,6 +169,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret += this.RawExecuteAffrows(); } } @@ -176,6 +185,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret += this.RawExecuteAffrows(); } _transaction.Commit(); @@ -211,6 +221,7 @@ namespace FreeSql.Internal.CommonProvider var ret = new List(); if (ss.Length <= 1) { + if (_source?.Any() == true) _batchProgress?.Invoke(new BatchProgressStatus(_source, 1, 1)); ret = this.RawExecuteUpdated(); ClearData(); return ret; @@ -228,6 +239,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret.AddRange(this.RawExecuteUpdated()); } } @@ -243,6 +255,7 @@ namespace FreeSql.Internal.CommonProvider for (var a = 0; a < ss.Length; a++) { _source = ss[a]; + _batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length)); ret.AddRange(this.RawExecuteUpdated()); } _transaction.Commit(); diff --git a/FreeSql/Internal/Model/BatchProgressEventArgs.cs b/FreeSql/Internal/Model/BatchProgressEventArgs.cs new file mode 100644 index 00000000..cb5d335b --- /dev/null +++ b/FreeSql/Internal/Model/BatchProgressEventArgs.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Text; + +namespace FreeSql.Internal.Model +{ + public class BatchProgressStatus + { + /// + /// 当前操作的数据 + /// + public IEnumerable Data { get; } + + /// + /// 当前批次 + /// + public int Current { get; } + + /// + /// 总批次数量 + /// + public int Total { get; } + + public BatchProgressStatus(List data, int current, int total) + { + this.Data = data; + this.Current = current; + this.Total = total; + } + } +} diff --git a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs index 7ee233bf..7b997653 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs @@ -6,6 +6,8 @@ using System.Data; using System.Linq; using System.Text; using System.Text.RegularExpressions; +using System.Data.Common; +using FreeSql.Internal.ObjectPool; #if MySqlConnector using MySqlConnector; #else @@ -85,28 +87,15 @@ namespace FreeSql.MySql protected override string GetComparisonDDLStatements(params TypeAndName[] objects) { - var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); - var database = conn.Value.Database; - Func ExecuteScalar = (db, sql) => - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); - try - { - using (var cmd = conn.Value.CreateCommand()) - { - cmd.CommandText = sql; - cmd.CommandType = CommandType.Text; - return cmd.ExecuteScalar(); - } - } - finally - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); - } - }; - var sb = new StringBuilder(); + Object conn = null; + string database = null; + try { + conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); + database = conn.Value.Database; + + var sb = new StringBuilder(); foreach (var obj in objects) { if (sb.Length > 0) sb.Append("\r\n"); @@ -129,17 +118,17 @@ namespace FreeSql.MySql } } - if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tbname[0])) == null) //创建数据库 + if (string.Compare(tbname[0], database, true) != 0 && LocalExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tbname[0])) == null) //创建数据库 sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(" default charset utf8 COLLATE utf8_general_ci;\r\n"); var sbalter = new StringBuilder(); var istmpatler = false; //创建临时表,导入数据,删除旧表,修改 - if (ExecuteScalar(tbname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tbname)) == null) + if (LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tbname)) == null) { //表不存在 if (tboldname != null) { - if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tboldname[0])) == null || - ExecuteScalar(tboldname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tboldname)) == null) + if (string.Compare(tboldname[0], tbname[0], true) != 0 && LocalExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tboldname[0])) == null || + LocalExecuteScalar(tboldname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tboldname)) == null) //数据库或表不存在 tboldname = null; } @@ -222,7 +211,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); if (istmpatler == false) { - var existsPrimary = ExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname)); + var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname)); foreach (var tbcol in tb.ColumnsByPosition) { var isIdentityChanged = tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1; @@ -385,7 +374,8 @@ where a.table_schema IN ({0}) and a.table_name IN ({1}) and a.index_name <> 'PRI { try { - conn.Value.ChangeDatabase(database); + if (string.IsNullOrEmpty(database) == false) + conn.Value.ChangeDatabase(database); _orm.Ado.MasterPool.Return(conn); } catch @@ -393,6 +383,24 @@ where a.table_schema IN ({0}) and a.table_name IN ({1}) and a.index_name <> 'PRI _orm.Ado.MasterPool.Return(conn, true); } } + + object LocalExecuteScalar(string db, string sql) + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); + try + { + using (var cmd = conn.Value.CreateCommand()) + { + cmd.CommandText = sql; + cmd.CommandType = CommandType.Text; + return cmd.ExecuteScalar(); + } + } + finally + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); + } + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs index 4832a458..6fc5f92d 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs @@ -1,8 +1,10 @@ using FreeSql.Internal; using FreeSql.Internal.Model; +using FreeSql.Internal.ObjectPool; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Data.Odbc; using System.Linq; using System.Text; @@ -74,28 +76,15 @@ namespace FreeSql.Odbc.MySql protected override string GetComparisonDDLStatements(params TypeAndName[] objects) { - var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); - var database = conn.Value.Database; - Func ExecuteScalar = (db, sql) => - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); - try - { - using (var cmd = conn.Value.CreateCommand()) - { - cmd.CommandText = sql; - cmd.CommandType = CommandType.Text; - return cmd.ExecuteScalar(); - } - } - finally - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); - } - }; - var sb = new StringBuilder(); + Object conn = null; + string database = null; + try { + conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); + database = conn.Value.Database; + + var sb = new StringBuilder(); foreach (var obj in objects) { if (sb.Length > 0) sb.Append("\r\n"); @@ -118,17 +107,17 @@ namespace FreeSql.Odbc.MySql } } - if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tbname[0])) == null) //创建数据库 + if (string.Compare(tbname[0], database, true) != 0 && LocalExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tbname[0])) == null) //创建数据库 sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(" default charset utf8 COLLATE utf8_general_ci;\r\n"); var sbalter = new StringBuilder(); var istmpatler = false; //创建临时表,导入数据,删除旧表,修改 - if (ExecuteScalar(tbname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tbname)) == null) + if (LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tbname)) == null) { //表不存在 if (tboldname != null) { - if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tboldname[0])) == null || - ExecuteScalar(tboldname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tboldname)) == null) + if (string.Compare(tboldname[0], tbname[0], true) != 0 && LocalExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tboldname[0])) == null || + LocalExecuteScalar(tboldname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tboldname)) == null) //数据库或表不存在 tboldname = null; } @@ -211,7 +200,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); if (istmpatler == false) { - var existsPrimary = ExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname)); + var existsPrimary = LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname)); foreach (var tbcol in tb.ColumnsByPosition) { var isIdentityChanged = tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1; @@ -374,7 +363,8 @@ where a.table_schema IN ({0}) and a.table_name IN ({1}) and a.index_name <> 'PRI { try { - conn.Value.ChangeDatabase(database); + if (string.IsNullOrEmpty(database) == false) + conn.Value.ChangeDatabase(database); _orm.Ado.MasterPool.Return(conn); } catch @@ -382,6 +372,24 @@ where a.table_schema IN ({0}) and a.table_name IN ({1}) and a.index_name <> 'PRI _orm.Ado.MasterPool.Return(conn, true); } } + + object LocalExecuteScalar(string db, string sql) + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); + try + { + using (var cmd = conn.Value.CreateCommand()) + { + cmd.CommandText = sql; + cmd.CommandType = CommandType.Text; + return cmd.ExecuteScalar(); + } + } + finally + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); + } + } } public override int ExecuteDDLStatements(string ddl) diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerCodeFirst.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerCodeFirst.cs index f319e1cb..8636b79b 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerCodeFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerCodeFirst.cs @@ -1,8 +1,10 @@ using FreeSql.Internal; using FreeSql.Internal.Model; +using FreeSql.Internal.ObjectPool; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Data.Odbc; using System.Linq; using System.Text; @@ -134,30 +136,15 @@ ELSE } protected override string GetComparisonDDLStatements(params TypeAndName[] objects) { - var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); + Object conn = null; string database = null; + try { + conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); database = conn.Value.Database; - Func ExecuteScalar = (db, sql) => - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); - try - { - using (var cmd = conn.Value.CreateCommand()) - { - cmd.CommandText = sql; - cmd.CommandType = CommandType.Text; - return cmd.ExecuteScalar(); - } - } - finally - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); - } - }; - var sb = new StringBuilder(); + var sb = new StringBuilder(); foreach (var obj in objects) { if (sb.Length > 0) sb.Append("\r\n"); @@ -184,20 +171,20 @@ ELSE } //codefirst 不支持表名、模式名、数据库名中带 . - if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库 - ExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];"); - if (string.Compare(tbname[1], "dbo", true) != 0 && ExecuteScalar(tbname[0], $" select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式 - ExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]"); + if (string.Compare(tbname[0], database, true) != 0 && LocalExecuteScalar(database, $" select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库 + LocalExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];"); + if (string.Compare(tbname[1], "dbo", true) != 0 && LocalExecuteScalar(tbname[0], $" select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式 + LocalExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]"); var sbalter = new StringBuilder(); var istmpatler = false; //创建临时表,导入数据,删除旧表,修改 - if (ExecuteScalar(tbname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) + if (LocalExecuteScalar(tbname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) { //表不存在 if (tboldname != null) { - if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tboldname[0]}'") == null || - string.Compare(tboldname[1], tbname[1], true) != 0 && ExecuteScalar(tboldname[0], $" select 1 from sys.schemas where name='{tboldname[1]}'") == null || - ExecuteScalar(tboldname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) + if (string.Compare(tboldname[0], tbname[0], true) != 0 && LocalExecuteScalar(database, $" select 1 from sys.databases where name='{tboldname[0]}'") == null || + string.Compare(tboldname[1], tbname[1], true) != 0 && LocalExecuteScalar(tboldname[0], $" select 1 from sys.schemas where name='{tboldname[1]}'") == null || + LocalExecuteScalar(tboldname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) //数据库或模式或表不存在 tboldname = null; } @@ -477,6 +464,24 @@ use [" + database + "];", tboldname ?? tbname); _orm.Ado.MasterPool.Return(conn, true); } } + + object LocalExecuteScalar(string db, string sql) + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); + try + { + using (var cmd = conn.Value.CreateCommand()) + { + cmd.CommandText = sql; + cmd.CommandType = CommandType.Text; + return cmd.ExecuteScalar(); + } + } + finally + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); + } + } } string GetTransferDbDefaultValue(ColumnInfo col) { diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs index ff1ab63a..a62f4e24 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs @@ -1,8 +1,10 @@ using FreeSql.Internal; using FreeSql.Internal.Model; +using FreeSql.Internal.ObjectPool; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; @@ -133,30 +135,15 @@ ELSE } protected override string GetComparisonDDLStatements(params TypeAndName[] objects) { - var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); + Object conn = null; string database = null; + try { + conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); database = conn.Value.Database; - Func ExecuteScalar = (db, sql) => - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); - try - { - using (var cmd = conn.Value.CreateCommand()) - { - cmd.CommandText = sql; - cmd.CommandType = CommandType.Text; - return cmd.ExecuteScalar(); - } - } - finally - { - if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); - } - }; - var sb = new StringBuilder(); + var sb = new StringBuilder(); foreach (var obj in objects) { if (sb.Length > 0) sb.Append("\r\n"); @@ -183,20 +170,20 @@ ELSE } //codefirst 不支持表名、模式名、数据库名中带 . - if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库 - ExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];"); - if (string.Compare(tbname[1], "dbo", true) != 0 && ExecuteScalar(tbname[0], $" select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式 - ExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]"); + if (string.Compare(tbname[0], database, true) != 0 && LocalExecuteScalar(database, $" select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库 + LocalExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];"); + if (string.Compare(tbname[1], "dbo", true) != 0 && LocalExecuteScalar(tbname[0], $" select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式 + LocalExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]"); var sbalter = new StringBuilder(); var istmpatler = false; //创建临时表,导入数据,删除旧表,修改 - if (ExecuteScalar(tbname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) + if (LocalExecuteScalar(tbname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) { //表不存在 if (tboldname != null) { - if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tboldname[0]}'") == null || - string.Compare(tboldname[1], tbname[1], true) != 0 && ExecuteScalar(tboldname[0], $" select 1 from sys.schemas where name='{tboldname[1]}'") == null || - ExecuteScalar(tboldname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) + if (string.Compare(tboldname[0], tbname[0], true) != 0 && LocalExecuteScalar(database, $" select 1 from sys.databases where name='{tboldname[0]}'") == null || + string.Compare(tboldname[1], tbname[1], true) != 0 && LocalExecuteScalar(tboldname[0], $" select 1 from sys.schemas where name='{tboldname[1]}'") == null || + LocalExecuteScalar(tboldname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) //数据库或模式或表不存在 tboldname = null; } @@ -476,6 +463,24 @@ use [" + database + "];", tboldname ?? tbname); _orm.Ado.MasterPool.Return(conn, true); } } + + object LocalExecuteScalar(string db, string sql) + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db); + try + { + using (var cmd = conn.Value.CreateCommand()) + { + cmd.CommandText = sql; + cmd.CommandType = CommandType.Text; + return cmd.ExecuteScalar(); + } + } + finally + { + if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database); + } + } } string GetTransferDbDefaultValue(ColumnInfo col) {