diff --git a/Examples/orm_vs/Program.cs b/Examples/orm_vs/Program.cs index 54f365a8..cd15bb85 100644 --- a/Examples/orm_vs/Program.cs +++ b/Examples/orm_vs/Program.cs @@ -23,8 +23,8 @@ namespace orm_vs { static IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Max Pool Size=21;TrustServerCertificate=true") - .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=21;AllowLoadLocalInfile=true;") - .UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=21") + //.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=21;AllowLoadLocalInfile=true;") + //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=21") .UseAutoSyncStructure(false) .UseNoneCommandParameter(true) //.UseConfigEntityFromDbFirst(true) @@ -36,12 +36,12 @@ namespace orm_vs { var db = new SqlSugarClient(new ConnectionConfig() { - //ConnectionString = "Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=20;Max Pool Size=20;TrustServerCertificate=true", - //DbType = DbType.SqlServer, + ConnectionString = "Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=20;Max Pool Size=20;TrustServerCertificate=true", + DbType = DbType.SqlServer, //ConnectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=20;Max Pool Size=20;AllowLoadLocalInfile=true;", //DbType = DbType.MySql, - ConnectionString = "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=20", - DbType = DbType.PostgreSQL, + //ConnectionString = "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=20", + //DbType = DbType.PostgreSQL, IsAutoCloseConnection = true, InitKeyType = InitKeyType.Attribute }); @@ -59,10 +59,10 @@ namespace orm_vs public DbSet PatientExamination_2022s { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - //optionsBuilder.UseSqlServer(@"Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=19;Max Pool Size=19;TrustServerCertificate=true"); + optionsBuilder.UseSqlServer(@"Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=19;Max Pool Size=19;TrustServerCertificate=true"); //var connectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=19;Max Pool Size=19"; //optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); - optionsBuilder.UseNpgsql("Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=19"); + //optionsBuilder.UseNpgsql("Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=19"); } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -576,14 +576,14 @@ namespace orm_vs sw.Stop(); sb.AppendLine($"EFCore Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms .net5.0无效"); - sw.Restart(); - using (var conn = fsql.Ado.MasterPool.Get()) - { - for (var a = 0; a < forTime; a++) - Dapper.SqlMapper.Query(conn.Value, $"select * from freesql_song limit {size}").ToList(); - } - sw.Stop(); - sb.AppendLine($"Dapper Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms\r\n"); + //sw.Restart(); + //using (var conn = fsql.Ado.MasterPool.Get()) + //{ + // for (var a = 0; a < forTime; a++) + // Dapper.SqlMapper.Query(conn.Value, $"select * from freesql_song limit {size}").ToList(); + //} + //sw.Stop(); + //sb.AppendLine($"Dapper Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms\r\n"); } static void Insert(StringBuilder sb, int forTime, int size) @@ -668,7 +668,7 @@ namespace orm_vs sw.Restart(); for (var a = 0; a < forTime; a++) { - fsql.Update().SetSource(songs).ExecutePgCopy(); + fsql.Update().SetSource(songs).ExecuteSqlBulkCopy(); } sw.Stop(); sb.AppendLine($"FreeSql BulkCopyUpdate {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms"); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs index e6c259e3..4e10ac87 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -181,6 +181,32 @@ namespace FreeSql.Tests.MySqlConnector Assert.Equal(TestEnumInserTbType.sum211, g.mysql.Select().Where(a => a.id == id).First()?.type); } + + [Table(Name = "tb_topic_insertbulk")] + class TopicBulk + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + [Fact] + public void ExecuteMySqlBulkCopy() + { + g.mysql.Delete().Where(a => true).ExecuteAffrows(); + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new TopicBulk { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + g.mysql.Insert(items).ExecuteMySqlBulkCopy(); + + items = g.mysql.Select().OrderByDescending(a => a.Id).Limit(1000).ToList(); + g.mysql.Update().SetSource(items).ExecuteMySqlBulkCopy(); + g.mysql.Update().SetSource(items, a => new { a.Id, a.Clicks }).ExecuteMySqlBulkCopy(); + g.mysql.Update().SetSource(items).UpdateColumns(a => new { a.Title }).ExecuteMySqlBulkCopy(); + g.mysql.Update().SetSource(items, a => new { a.Id, a.Clicks }).UpdateColumns(a => new { a.Title }).ExecuteMySqlBulkCopy(); + } + [Fact] public void AsTable() { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs index cb2c3de6..e18b2c02 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/g.cs @@ -8,7 +8,7 @@ public class g { static Lazy mysqlLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() - .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10;AllowLoadLocalInfile=true") + .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10;AllowLoadLocalInfile=true;AllowZeroDateTime=True ") //.UseConnectionFactory(FreeSql.DataType.MySql, () => new MySql.Data.MySqlClient.MySqlConnection("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;")) //.UseConnectionString(FreeSql.DataType.MySql, "Data Source=192.168.164.10;Port=33061;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10") .UseAutoSyncStructure(true) diff --git a/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml b/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml index 46e1feb0..03c7cd98 100644 --- a/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml +++ b/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.xml @@ -4,6 +4,126 @@ FreeSql.Tests + + + 实时数据 + + + + + Guid + + + + + 租户Id + + + + + 版本 + + + + + 是否删除 + + + + + 创建者Id + + + + + 创建者 + + + + + 创建时间 + + + + + 修改者Id + + + + + 修改者 + + + + + 修改时间 + + + + + 数据标识 + + + + + 主键Id + + + + + 设备编号 + + + + + 数据编号,如为空使用默认数据 + + + + + 数据名称,如为空使用默认数据 + + + + + 数值或状态是否变更 + + + + + 采集数值 + + + + + 备注 + + + + + 服务标记 + + + + + 状态 + + + + + 文本数值 + + + + + 单位 + + + + + 采集时间 + + 编号 diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs index 6e05d833..1e951e68 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -137,6 +137,23 @@ namespace FreeSql.Tests.PostgreSQL insert.AppendData(items.First()).ExecuteInserted(); } + [Fact] + public void ExecutePgCopy() + { + var maxId = g.pgsql.Select().Max(a => a.Id); + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = maxId + a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + insert.AppendData(items).InsertIdentity().ExecutePgCopy(); + + items = g.pgsql.Select().OrderByDescending(a => a.Id).Limit(1000).ToList(); + var sql = g.pgsql.Insert(items).InsertIdentity().NoneParameter().ToSql(); + g.pgsql.Update().SetSource(items).ExecutePgCopy(); + g.pgsql.Update().SetSource(items, a => new { a.Id, a.Clicks }).ExecutePgCopy(); + g.pgsql.Update().SetSource(items).UpdateColumns(a => new { a.Title }).ExecutePgCopy(); + g.pgsql.Update().SetSource(items, a => new { a.Id, a.Clicks }).UpdateColumns(a => new { a.Title }).ExecutePgCopy(); + } + [Fact] public void AsTable() { diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs index c0cc53f3..a960da06 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs @@ -227,12 +227,19 @@ namespace FreeSql.Tests.SqlServer [Fact] public void ExecuteSqlBulkCopy() { + var maxId = g.pgsql.Select().Max(a => a.Id); var items = new List(); - for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = maxId + a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); insert.AppendData(items).InsertIdentity().ExecuteSqlBulkCopy(); //insert.AppendData(items).IgnoreColumns(a => new { a.CreateTime, a.Clicks }).ExecuteSqlBulkCopy(); // System.NotSupportedException:“DataSet does not support System.Nullable<>.” + + items = g.sqlserver.Select().OrderByDescending(a => a.Id).Limit(1000).ToList(); + g.sqlserver.Update().SetSource(items).ExecuteSqlBulkCopy(); + g.sqlserver.Update().SetSource(items, a => new { a.Id, a.TypeGuid }).ExecuteSqlBulkCopy(); + g.sqlserver.Update().SetSource(items).UpdateColumns(a => new { a.Title }).ExecuteSqlBulkCopy(); + g.sqlserver.Update().SetSource(items, a => new { a.Id, a.TypeGuid }).UpdateColumns(a => new { a.Title }).ExecuteSqlBulkCopy(); } [Fact] diff --git a/FreeSql/Internal/CommonProvider/DeleteProvider.cs b/FreeSql/Internal/CommonProvider/DeleteProvider.cs index d77837d4..58bca8e8 100644 --- a/FreeSql/Internal/CommonProvider/DeleteProvider.cs +++ b/FreeSql/Internal/CommonProvider/DeleteProvider.cs @@ -25,6 +25,7 @@ namespace FreeSql.Internal.CommonProvider public DbConnection _connection; public int _commandTimeout = 0; public Action _interceptSql; + public bool _isAutoSyncStructure; } public abstract partial class DeleteProvider : DeleteProvider, IDelete @@ -35,8 +36,9 @@ namespace FreeSql.Internal.CommonProvider _commonUtils = commonUtils; _commonExpression = commonExpression; _table = _commonUtils.GetTableByEntity(typeof(T1)); + _isAutoSyncStructure = _orm.CodeFirst.IsAutoSyncStructure; this.Where(_commonUtils.WhereObject(_table, "", dywhere)); - if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); + if (_isAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); _whereGlobalFilter = _orm.GlobalFilter.GetFilters(); } @@ -145,7 +147,7 @@ namespace FreeSql.Internal.CommonProvider if (string.IsNullOrEmpty(newname)) return _table.DbName; if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower(); if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper(); - if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname); + if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname); return newname; } public IDelete AsTable(Func tableRule) @@ -164,7 +166,7 @@ namespace FreeSql.Internal.CommonProvider if (entityType == _table.Type) return this; var newtb = _commonUtils.GetTableByEntity(entityType); _table = newtb ?? throw new Exception(CoreStrings.Type_AsType_Parameter_Error("IDelete")); - if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType); + if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType); return this; } diff --git a/FreeSql/Internal/CommonProvider/InsertProvider.cs b/FreeSql/Internal/CommonProvider/InsertProvider.cs index 20562e3c..7bd2e76e 100644 --- a/FreeSql/Internal/CommonProvider/InsertProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertProvider.cs @@ -31,6 +31,7 @@ namespace FreeSql.Internal.CommonProvider public DbTransaction _transaction; public DbConnection _connection; public int _commandTimeout = 0; + public bool _isAutoSyncStructure; } public abstract partial class InsertProvider : InsertProvider, IInsert where T1 : class @@ -46,7 +47,8 @@ namespace FreeSql.Internal.CommonProvider _commonExpression = commonExpression; _table = _commonUtils.GetTableByEntity(typeof(T1)); _noneParameter = _orm.CodeFirst.IsNoneCommandParameter; - if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); + _isAutoSyncStructure = _orm.CodeFirst.IsAutoSyncStructure; + if (_isAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); IgnoreCanInsert(); _sourceOld = _source; } @@ -568,7 +570,7 @@ namespace FreeSql.Internal.CommonProvider if (string.IsNullOrEmpty(newname)) return tbname; if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower(); if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper(); - if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table?.Type, newname); + if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table?.Type, newname); return newname; } public IInsert AsTable(Func tableRule) @@ -588,7 +590,7 @@ namespace FreeSql.Internal.CommonProvider if (entityType == _table.Type) return this; var newtb = _commonUtils.GetTableByEntity(entityType); _table = newtb ?? throw new Exception(CoreStrings.Type_AsType_Parameter_Error("IInsert")); - if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType); + if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType); IgnoreCanInsert(); return this; } diff --git a/FreeSql/Internal/CommonProvider/UpdateProvider.cs b/FreeSql/Internal/CommonProvider/UpdateProvider.cs index 617c36af..3ed7697e 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProvider.cs @@ -38,9 +38,10 @@ namespace FreeSql.Internal.CommonProvider public int _commandTimeout = 0; public Action _interceptSql; public object _updateVersionValue; + public bool _isAutoSyncStructure; - public static int ExecuteBulkUpdate(UpdateProvider update, NativeTuple state, Action> funcBulkCopy) where T1 : class + public static int ExecuteBulkUpdate(UpdateProvider update, NativeTuple state, Action> funcBulkCopy) where T1 : class { if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0; var fsql = update._orm; @@ -59,12 +60,16 @@ namespace FreeSql.Internal.CommonProvider fsql.Ado.CommandFluent(state.Item1).WithConnection(connection).WithTransaction(transaction).ExecuteNonQuery(); try { - funcBulkCopy(fsql.Insert(update._source) + var insert = fsql.Insert(update._source) .AsType(update._table.Type) .WithConnection(connection) .WithTransaction(transaction) - .InsertIdentity().AsTable(state.Item4)); - var affrows = fsql.Ado.CommandFluent(state.Item2 + ";" + state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQuery(); + .InsertIdentity() + .InsertColumns(state.Item5) + .AsTable(state.Item4); + (insert as InsertProvider)._isAutoSyncStructure = false; + funcBulkCopy(insert); + var affrows = fsql.Ado.CommandFluent(state.Item2 + ";\r\n" + state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQuery(); droped = true; return affrows; } @@ -80,7 +85,7 @@ namespace FreeSql.Internal.CommonProvider } #if net40 #else - async public static Task ExecuteBulkUpdateAsync(UpdateProvider update, NativeTuple state, Func, Task> funcBulkCopy) where T1 : class + async public static Task ExecuteBulkUpdateAsync(UpdateProvider update, NativeTuple state, Func, Task> funcBulkCopy) where T1 : class { if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0; var fsql = update._orm; @@ -99,12 +104,16 @@ namespace FreeSql.Internal.CommonProvider await fsql.Ado.CommandFluent(state.Item1).WithConnection(connection).WithTransaction(transaction).ExecuteNonQueryAsync(); try { - await funcBulkCopy(fsql.Insert(update._source) + var insert = fsql.Insert(update._source) .AsType(update._table.Type) .WithConnection(connection) .WithTransaction(transaction) - .InsertIdentity().AsTable(state.Item4)); - var affrows = await fsql.Ado.CommandFluent(state.Item2 + ";" + state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQueryAsync(); + .InsertIdentity() + .InsertColumns(state.Item5) + .AsTable(state.Item4); + (insert as InsertProvider)._isAutoSyncStructure = false; + await funcBulkCopy(insert); + var affrows = await fsql.Ado.CommandFluent(state.Item2 + ";\r\n" + state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQueryAsync(); droped = true; return affrows; } @@ -136,8 +145,9 @@ namespace FreeSql.Internal.CommonProvider _tempPrimarys = _table?.Primarys ?? new ColumnInfo[0]; _versionColumn = _table?.VersionColumn; _noneParameter = _orm.CodeFirst.IsNoneCommandParameter; + _isAutoSyncStructure = _orm.CodeFirst.IsAutoSyncStructure; this.Where(_commonUtils.WhereObject(_table, "", dywhere)); - if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); + if (_isAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); IgnoreCanUpdate(); _whereGlobalFilter = _orm.GlobalFilter.GetFilters(); _sourceOld = _source; @@ -879,7 +889,7 @@ namespace FreeSql.Internal.CommonProvider if (string.IsNullOrEmpty(newname)) return _table.DbName; if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower(); if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper(); - if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname); + if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname); return newname; } public IUpdate AsTable(Func tableRule) @@ -900,7 +910,7 @@ namespace FreeSql.Internal.CommonProvider _table = newtb ?? throw new Exception(CoreStrings.Type_AsType_Parameter_Error("IUpdate")); _tempPrimarys = _table.Primarys; _versionColumn = _ignoreVersion ? null : _table.VersionColumn; - if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType); + if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType); IgnoreCanUpdate(); return this; } diff --git a/Providers/FreeSql.Provider.MySqlConnector/FreeSqlMySqlConnectorGlobalExtensions.cs b/Providers/FreeSql.Provider.MySqlConnector/FreeSqlMySqlConnectorGlobalExtensions.cs index efde19d2..0cbb6324 100644 --- a/Providers/FreeSql.Provider.MySqlConnector/FreeSqlMySqlConnectorGlobalExtensions.cs +++ b/Providers/FreeSql.Provider.MySqlConnector/FreeSqlMySqlConnectorGlobalExtensions.cs @@ -34,60 +34,37 @@ public static class FreeSqlMySqlConnectorGlobalExtensions var state = ExecuteMySqlBulkCopyState(update); return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteMySqlBulkCopy(bulkCopyTimeout)); } - static NativeTuple ExecuteMySqlBulkCopyState(UpdateProvider update) where T : class + static NativeTuple ExecuteMySqlBulkCopyState(UpdateProvider update) where T : class { if (update._source.Any() != true) return null; var _table = update._table; - var _tempPrimarys = update._tempPrimarys; var _commonUtils = update._commonUtils; - var _ignore = update._ignore; var updateTableName = update._tableRule?.Invoke(_table.DbName) ?? _table.DbName; var tempTableName = $"Temp_{Guid.NewGuid().ToString("N")}"; - if (update._connection == null) + if (update._orm.CodeFirst.IsSyncStructureToLower) tempTableName = tempTableName.ToLower(); + if (update._orm.CodeFirst.IsSyncStructureToUpper) tempTableName = tempTableName.ToUpper(); + if (update._connection == null && update._orm.Ado.TransactionCurrentThread != null) + update.WithTransaction(update._orm.Ado.TransactionCurrentThread); + var sb = new StringBuilder().Append("CREATE TEMPORARY TABLE ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" ( "); + var setColumns = new List(); + var pkColumns = new List(); + foreach (var col in _table.Columns.Values) { - if (update._orm.Ado.TransactionCurrentThread != null) - update.WithTransaction(update._orm.Ado.TransactionCurrentThread); - } - var sb = new StringBuilder(); - sb.Append("CREATE TEMPORARY TABLE ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" ( "); - foreach (var tbcol in _table.ColumnsByPosition) - { - sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType); + if (update._tempPrimarys.Any(a => a.CsName == col.CsName)) pkColumns.Add(col.Attribute.Name); + else if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && update._ignore.ContainsKey(col.Attribute.Name) == false) setColumns.Add(col.Attribute.Name); + else continue; + sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" ").Append(col.Attribute.DbType.Replace("NOT NULL", "")); sb.Append(","); } - //if (_tempPrimarys.Any()) - //{ - // sb.Append(" \r\n PRIMARY KEY ("); - // foreach (var tbcol in _tempPrimarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); - // sb.Remove(sb.Length - 2, 2).Append("),"); - //} var sql1 = sb.Remove(sb.Length - 1, 1).Append(" \r\n) Engine=InnoDB;").ToString(); sb.Clear().Append("UPDATE ").Append(_commonUtils.QuoteSqlName(updateTableName)).Append(" a ") - .Append(" \r\nINNER JOIN ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" b ON "); - for (var a = 0; a < _tempPrimarys.Length; a++) - { - var pkname = _commonUtils.QuoteSqlName(_tempPrimarys[a].Attribute.Name); - if (a > 0) sb.Append(" AND "); - sb.Append("b.").Append(pkname).Append(" = a.").Append(pkname); - } - sb.Append("\r\n SET "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (col.Attribute.IsPrimary) continue; - if (_tempPrimarys.Any(a => a.CsName == col.CsName)) continue; - if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && _ignore.ContainsKey(col.Attribute.Name) == false) - { - if (colidx > 0) sb.Append(","); - sb.Append(" \r\n a.").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append("b.").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)); - ++colidx; - } - } + .Append(" \r\nINNER JOIN ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" b ON ").Append(string.Join(" AND ", pkColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}"))) + .Append(" \r\nSET \r\n ").Append(string.Join(", \r\n ", setColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}"))); var sql2 = sb.ToString(); sb.Clear(); var sql3 = $"DROP TABLE {_commonUtils.QuoteSqlName(tempTableName)}"; - return NativeTuple.Create(sql1, sql2, sql3, tempTableName); + return NativeTuple.Create(sql1, sql2, sql3, tempTableName, pkColumns.Concat(setColumns).ToArray()); } /// diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExtensions.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExtensions.cs index 313ce549..a85c7166 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExtensions.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExtensions.cs @@ -4,6 +4,7 @@ using FreeSql.Internal.Model; using FreeSql.PostgreSQL.Curd; using Npgsql; using System; +using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; @@ -49,53 +50,38 @@ public static partial class FreeSqlPostgreSQLGlobalExtensions var state = ExecutePgCopyState(update); return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecutePgCopy()); } - static NativeTuple ExecutePgCopyState(UpdateProvider update) where T : class + static NativeTuple ExecutePgCopyState(UpdateProvider update) where T : class { if (update._source.Any() != true) return null; var _table = update._table; - var _tempPrimarys = update._tempPrimarys; var _commonUtils = update._commonUtils; - var _ignore = update._ignore; var updateTableName = update._tableRule?.Invoke(_table.DbName) ?? _table.DbName; var tempTableName = $"Temp_{Guid.NewGuid().ToString("N")}"; - if (update._connection == null) + if (update._orm.CodeFirst.IsSyncStructureToLower) tempTableName = tempTableName.ToLower(); + if (update._orm.CodeFirst.IsSyncStructureToUpper) tempTableName = tempTableName.ToUpper(); + if (update._connection == null && update._orm.Ado.TransactionCurrentThread != null) + update.WithTransaction(update._orm.Ado.TransactionCurrentThread); + var sb = new StringBuilder().Append("CREATE TEMP TABLE ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" ( "); + var setColumns = new List(); + var pkColumns = new List(); + foreach (var col in _table.Columns.Values) { - if (update._orm.Ado.TransactionCurrentThread != null) - update.WithTransaction(update._orm.Ado.TransactionCurrentThread); - } - var sb = new StringBuilder(); - sb.Append("CREATE TEMP TABLE ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" ( "); - foreach (var tbcol in _table.ColumnsByPosition) - { - sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType); + if (update._tempPrimarys.Any(a => a.CsName == col.CsName)) pkColumns.Add(col.Attribute.Name); + else if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && update._ignore.ContainsKey(col.Attribute.Name) == false) setColumns.Add(col.Attribute.Name); + else continue; + sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" ").Append(col.Attribute.DbType.Replace("NOT NULL", "")); sb.Append(","); } var sql1 = sb.Remove(sb.Length - 1, 1).Append("\r\n) WITH (OIDS=FALSE);").ToString(); - sb.Clear().Append("UPDATE ").Append(_commonUtils.QuoteSqlName(updateTableName)).Append(" a \r\nSET "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (col.Attribute.IsPrimary) continue; - if (_tempPrimarys.Any(a => a.CsName == col.CsName)) continue; - if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && _ignore.ContainsKey(col.Attribute.Name) == false) - { - if (colidx > 0) sb.Append(","); - sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append("b.").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)); - ++colidx; - } - } - sb.Append(" \r\nFROM ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" b \r\nWHERE "); - for (var a = 0; a < _tempPrimarys.Length; a++) - { - var pkname = _commonUtils.QuoteSqlName(_tempPrimarys[a].Attribute.Name); - if (a > 0) sb.Append(" AND "); - sb.Append("b.").Append(pkname).Append(" = a.").Append(pkname); - } + sb.Clear().Append("UPDATE ").Append(_commonUtils.QuoteSqlName(updateTableName)).Append(" a ") + .Append("\r\nSET \r\n ").Append(string.Join(", \r\n ", setColumns.Select(col => $"{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}"))) + .Append("\r\nFROM ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" b ") + .Append("\r\nWHERE ").Append(string.Join(" AND ", pkColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}"))); var sql2 = sb.ToString(); sb.Clear(); var sql3 = $"DROP TABLE {_commonUtils.QuoteSqlName(tempTableName)}"; - return NativeTuple.Create(sql1, sql2, sql3, tempTableName); + return NativeTuple.Create(sql1, sql2, sql3, tempTableName, pkColumns.Concat(setColumns).ToArray()); } /// diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs index 01cf9e24..91880a60 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs @@ -136,46 +136,32 @@ public static partial class FreeSqlSqlServerGlobalExtensions var state = ExecuteSqlBulkCopyState(update); return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteSqlBulkCopy(copyOptions, batchSize, bulkCopyTimeout)); } - static NativeTuple ExecuteSqlBulkCopyState(UpdateProvider update) where T : class + static NativeTuple ExecuteSqlBulkCopyState(UpdateProvider update) where T : class { if (update._source.Any() != true) return null; var _table = update._table; - var _tempPrimarys = update._tempPrimarys; var _commonUtils = update._commonUtils; - var _ignore = update._ignore; var updateTableName = update._tableRule?.Invoke(_table.DbName) ?? _table.DbName; var tempTableName = $"#Temp_{updateTableName}"; - if (update._connection == null) - { - if (update._orm.Ado.TransactionCurrentThread != null) + if (update._orm.CodeFirst.IsSyncStructureToLower) tempTableName = tempTableName.ToLower(); + if (update._orm.CodeFirst.IsSyncStructureToUpper) tempTableName = tempTableName.ToUpper(); + if (update._connection == null && update._orm.Ado.TransactionCurrentThread != null) update.WithTransaction(update._orm.Ado.TransactionCurrentThread); - } - var sql1 = $"SELECT * INTO {tempTableName} FROM {_commonUtils.QuoteSqlName(updateTableName)} WHERE 1=2"; - var sb = new StringBuilder().Append("UPDATE ").Append(" a SET \r\n "); - var colidx = 0; + var setColumns = new List(); + var pkColumns = new List(); foreach (var col in _table.Columns.Values) { - if (col.Attribute.IsPrimary) continue; - if (_tempPrimarys.Any(a => a.CsName == col.CsName)) continue; - if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && _ignore.ContainsKey(col.Attribute.Name) == false) - { - if (colidx > 0) sb.Append(", \r\n "); - sb.Append(" a.").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append("b.").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)); - ++colidx; - } + if (update._tempPrimarys.Any(a => a.CsName == col.CsName)) pkColumns.Add(col.Attribute.Name); + else if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && update._ignore.ContainsKey(col.Attribute.Name) == false) setColumns.Add(col.Attribute.Name); } + var sql1 = $"SELECT {string.Join(", ", pkColumns)}, {string.Join(", ", setColumns)} INTO {tempTableName} FROM {_commonUtils.QuoteSqlName(updateTableName)} WHERE 1=2"; + var sb = new StringBuilder().Append("UPDATE ").Append(" a SET \r\n ").Append(string.Join(", \r\n ", setColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}"))); sb.Append(" \r\nFROM ").Append(_commonUtils.QuoteSqlName(updateTableName)).Append(" a ") - .Append(" \r\nINNER JOIN ").Append(tempTableName).Append(" b ON "); - for (var a = 0; a < _tempPrimarys.Length; a++) - { - var pkname = _commonUtils.QuoteSqlName(_tempPrimarys[a].Attribute.Name); - if (a > 0) sb.Append(" AND "); - sb.Append("b.").Append(pkname).Append(" = a.").Append(pkname); - } + .Append(" \r\nINNER JOIN ").Append(tempTableName).Append(" b ON ").Append(string.Join(" AND ", pkColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}"))); var sql2 = sb.ToString(); sb.Clear(); var sql3 = $"DROP TABLE {tempTableName}"; - return NativeTuple.Create(sql1, sql2, sql3, tempTableName); + return NativeTuple.Create(sql1, sql2, sql3, tempTableName, pkColumns.Concat(setColumns).ToArray()); } ///