- 修复 SqlServer 自增 BulkUpdate bug;#1476

This commit is contained in:
2881099 2023-03-29 19:07:19 +08:00
parent 8c2ebe3234
commit 1e23938e4e
5 changed files with 101 additions and 10 deletions

View File

@ -27,6 +27,16 @@ public class RoleUser1 : BaseEntity<RoleUser1>
public User1 User1 { get; set; } public User1 User1 { get; set; }
} }
public class IdentityUser1
{
[Column(IsIdentity = true)]
public int Id { get; set; }
[MaxLength(32)]
public string Username { get; set; }
[MaxLength(64)]
public string Nickname { get; set; }
}
public class User1 : BaseEntity<User1, Guid> public class User1 : BaseEntity<User1, Guid>
{ {
public int GroupId { get; set; } public int GroupId { get; set; }

View File

@ -0,0 +1,45 @@
using FreeSql;
using FreeSql.DataAnnotations;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
class ModAsTableImpl : IAsTable
{
public ModAsTableImpl(IFreeSql fsql)
{
AllTables = Enumerable.Range(0, 9).Select(a => $"order_{a}").ToArray();
fsql.Aop.CommandBefore += (_, e) =>
{
e.Command.CommandText = Regex.Replace(e.Command.CommandText, @"/\*astable\([^\)]+\)*\/", "1=1");
};
}
public string[] AllTables { get; }
public string GetTableNameByColumnValue(object columnValue, bool autoExpand = false)
{
var modid = (int)columnValue;
return $"order_{(modid % 10)}";
}
public string[] GetTableNamesByColumnValueRange(object columnValue1, object columnValue2)
{
throw new NotImplementedException();
}
public string[] GetTableNamesBySqlWhere(string sqlWhere, List<DbParameter> dbParams, SelectTableInfo tb, CommonUtils commonUtils)
{
var match = Regex.Match(sqlWhere, @"/\*astable\([^\)]+\)*\/");
if (match.Success == false) return AllTables;
var tables = match.Groups[1].Value.Split(',').Where(a => AllTables.Contains(a)).ToArray();
if (tables.Any() == false) return AllTables;
return tables;
}
}

View File

@ -6,6 +6,7 @@ using FreeSql.Internal;
using FreeSql.Internal.CommonProvider; using FreeSql.Internal.CommonProvider;
using FreeSql.Internal.Model; using FreeSql.Internal.Model;
using FreeSql.Odbc.Default; using FreeSql.Odbc.Default;
using Microsoft.Data.SqlClient;
using NetTopologySuite.Geometries; using NetTopologySuite.Geometries;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -541,7 +542,7 @@ namespace base_entity
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=2;AllowLoadLocalInfile=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;min pool size=1;Max pool size=2;AllowLoadLocalInfile=true")
//.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true") .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true")
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2")
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=toc;Pooling=true;Maximum Pool Size=2") //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=toc;Pooling=true;Maximum Pool Size=2")
@ -576,6 +577,23 @@ namespace base_entity
BaseEntity.Initialization(fsql, () => _asyncUow.Value); BaseEntity.Initialization(fsql, () => _asyncUow.Value);
#endregion #endregion
var bulkUsers = new[] {
new IdentityUser1 { Nickname = "nickname11", Username = "username11" },
new IdentityUser1 { Nickname = "nickname12", Username = "username12" },
new IdentityUser1 { Nickname = "nickname13", Username = "username13" },
new IdentityUser1 { Nickname = "nickname21", Username = "username21" },
new IdentityUser1 { Nickname = "nickname22", Username = "username22" },
new IdentityUser1 { Nickname = "nickname23", Username = "username23" }
};
fsql.Insert(bulkUsers).NoneParameter().ExecuteAffrows();
bulkUsers = fsql.Select<IdentityUser1>().OrderByDescending(a => a.Id).Limit(3).ToList().ToArray();
bulkUsers[0].Nickname += "_bulkupdate";
bulkUsers[1].Nickname += "_bulkupdate";
bulkUsers[2].Nickname += "_bulkupdate";
fsql.Update<IdentityUser1>().SetSource(bulkUsers).ExecuteSqlBulkCopy();
var objtsql1 = fsql.Select<object>().WithSql("select * from user1").ToList(); var objtsql1 = fsql.Select<object>().WithSql("select * from user1").ToList();
var objtsql2 = fsql.Select<object>().WithSql("select * from user1").ToList<User1>(); var objtsql2 = fsql.Select<object>().WithSql("select * from user1").ToList<User1>();
@ -585,8 +603,8 @@ namespace base_entity
.ToSql(); .ToSql();
var table = fsql.CodeFirst.GetTableByEntity(typeof(AsTableLog)); //var table = fsql.CodeFirst.GetTableByEntity(typeof(AsTableLog));
//table.SetAsTable(null, table.ColumnsByCs[nameof(AsTableLog.createtime)]); //table.SetAsTable(new ModAsTableImpl(fsql), table.ColumnsByCs[nameof(AsTableLog.click)]);
var testitems = new[] var testitems = new[]
@ -598,9 +616,9 @@ namespace base_entity
new AsTableLog{ msg = "msg05", createtime = DateTime.Parse("2022-3-8 15:00:13"), click = 5 }, new AsTableLog{ msg = "msg05", createtime = DateTime.Parse("2022-3-8 15:00:13"), click = 5 },
new AsTableLog{ msg = "msg06", createtime = DateTime.Parse("2022-4-8 15:00:13"), click = 6 }, new AsTableLog{ msg = "msg06", createtime = DateTime.Parse("2022-4-8 15:00:13"), click = 6 },
new AsTableLog{ msg = "msg07", createtime = DateTime.Parse("2022-6-8 15:00:13"), click = 7 }, new AsTableLog{ msg = "msg07", createtime = DateTime.Parse("2022-6-8 15:00:13"), click = 7 },
new AsTableLog{ msg = "msg08", createtime = DateTime.Parse("2022-7-1"), click = 8}, new AsTableLog{ msg = "msg08", createtime = DateTime.Parse("2022-7-1"), click = 9},
new AsTableLog{ msg = "msg09", createtime = DateTime.Parse("2022-7-1 11:00:00"), click = 8} new AsTableLog{ msg = "msg09", createtime = DateTime.Parse("2022-7-1 11:00:00"), click = 10},
new AsTableLog{ msg = "msg10", createtime = DateTime.Parse("2022-7-1 12:00:00"), click = 10}
}; };
var sqlatb = fsql.Insert(testitems).NoneParameter(); var sqlatb = fsql.Insert(testitems).NoneParameter();
var sqlat = sqlatb.ToSql(); var sqlat = sqlatb.ToSql();

View File

@ -733,6 +733,15 @@
<param name="modelBuilder"></param> <param name="modelBuilder"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:FreeSqlDbContextExtensions.ApplyConfigurationsFromAssembly(FreeSql.ICodeFirst,System.Reflection.Assembly,System.Func{System.Type,System.Boolean})">
<summary>
根据Assembly扫描所有继承IEntityTypeConfiguration&lt;T&gt;的配置类
</summary>
<param name="codeFirst"></param>
<param name="assembly"></param>
<param name="predicate"></param>
<returns></returns>
</member>
<member name="M:FreeSqlDbContextExtensions.CreateDbContext(IFreeSql)"> <member name="M:FreeSqlDbContextExtensions.CreateDbContext(IFreeSql)">
<summary> <summary>
创建普通数据上下文档对象 创建普通数据上下文档对象
@ -791,5 +800,14 @@
<param name="that"></param> <param name="that"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
<summary>
批量注入 Repository可以参考代码自行调整
</summary>
<param name="services"></param>
<param name="globalDataFilter"></param>
<param name="assemblies"></param>
<returns></returns>
</member>
</members> </members>
</doc> </doc>

View File

@ -134,7 +134,7 @@ public static partial class FreeSqlSqlServerGlobalExtensions
var upsert = that as InsertOrUpdateProvider<T>; var upsert = that as InsertOrUpdateProvider<T>;
if (upsert._source.Any() != true || upsert._tempPrimarys.Any() == false) return 0; if (upsert._source.Any() != true || upsert._tempPrimarys.Any() == false) return 0;
var state = ExecuteSqlBulkCopyState(upsert); var state = ExecuteSqlBulkCopyState(upsert);
return UpdateProvider.ExecuteBulkUpsert(upsert, state, insert => insert.ExecuteSqlBulkCopy(copyOptions, batchSize, bulkCopyTimeout)); return UpdateProvider.ExecuteBulkUpsert(upsert, state, insert => insert.ExecuteSqlBulkCopy(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout));
} }
static NativeTuple<string, string, string, string, string[]> ExecuteSqlBulkCopyState<T>(InsertOrUpdateProvider<T> upsert) where T : class static NativeTuple<string, string, string, string, string[]> ExecuteSqlBulkCopyState<T>(InsertOrUpdateProvider<T> upsert) where T : class
{ {
@ -175,7 +175,7 @@ public static partial class FreeSqlSqlServerGlobalExtensions
var update = that as UpdateProvider<T>; var update = that as UpdateProvider<T>;
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0; if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0;
var state = ExecuteSqlBulkCopyState(update); var state = ExecuteSqlBulkCopyState(update);
return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteSqlBulkCopy(copyOptions, batchSize, bulkCopyTimeout)); return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteSqlBulkCopy(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout));
} }
static NativeTuple<string, string, string, string, string[]> ExecuteSqlBulkCopyState<T>(UpdateProvider<T> update) where T : class static NativeTuple<string, string, string, string, string[]> ExecuteSqlBulkCopyState<T>(UpdateProvider<T> update) where T : class
{ {
@ -309,14 +309,14 @@ public static partial class FreeSqlSqlServerGlobalExtensions
var upsert = that as InsertOrUpdateProvider<T>; var upsert = that as InsertOrUpdateProvider<T>;
if (upsert._source.Any() != true || upsert._tempPrimarys.Any() == false) return Task.FromResult(0); if (upsert._source.Any() != true || upsert._tempPrimarys.Any() == false) return Task.FromResult(0);
var state = ExecuteSqlBulkCopyState(upsert); var state = ExecuteSqlBulkCopyState(upsert);
return UpdateProvider.ExecuteBulkUpsertAsync(upsert, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions, batchSize, bulkCopyTimeout, cancellationToken)); return UpdateProvider.ExecuteBulkUpsertAsync(upsert, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout, cancellationToken));
} }
public static Task<int> ExecuteSqlBulkCopyAsync<T>(this IUpdate<T> that, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, int? batchSize = null, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class public static Task<int> ExecuteSqlBulkCopyAsync<T>(this IUpdate<T> that, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, int? batchSize = null, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class
{ {
var update = that as UpdateProvider<T>; var update = that as UpdateProvider<T>;
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return Task.FromResult(0); if (update._source.Any() != true || update._tempPrimarys.Any() == false) return Task.FromResult(0);
var state = ExecuteSqlBulkCopyState(update); var state = ExecuteSqlBulkCopyState(update);
return UpdateProvider.ExecuteBulkUpdateAsync(update, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions, batchSize, bulkCopyTimeout, cancellationToken)); return UpdateProvider.ExecuteBulkUpdateAsync(update, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout, cancellationToken));
} }
async public static Task ExecuteSqlBulkCopyAsync<T>(this IInsert<T> that, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, int? batchSize = null, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class async public static Task ExecuteSqlBulkCopyAsync<T>(this IInsert<T> that, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, int? batchSize = null, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class
{ {