Skip to content

Commit 1e23938

Browse files
committed
- 修复 SqlServer 自增 BulkUpdate bug;#1476
1 parent 8c2ebe3 commit 1e23938

File tree

5 files changed

+101
-10
lines changed

5 files changed

+101
-10
lines changed

Examples/base_entity/Entities/User.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ public class RoleUser1 : BaseEntity<RoleUser1>
2727
public User1 User1 { get; set; }
2828
}
2929

30+
public class IdentityUser1
31+
{
32+
[Column(IsIdentity = true)]
33+
public int Id { get; set; }
34+
[MaxLength(32)]
35+
public string Username { get; set; }
36+
[MaxLength(64)]
37+
public string Nickname { get; set; }
38+
}
39+
3040
public class User1 : BaseEntity<User1, Guid>
3141
{
3242
public int GroupId { get; set; }
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using FreeSql;
2+
using FreeSql.DataAnnotations;
3+
using FreeSql.Internal;
4+
using FreeSql.Internal.Model;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Data.Common;
8+
using System.Linq;
9+
using System.Text;
10+
using System.Text.RegularExpressions;
11+
using System.Threading.Tasks;
12+
13+
class ModAsTableImpl : IAsTable
14+
{
15+
public ModAsTableImpl(IFreeSql fsql)
16+
{
17+
AllTables = Enumerable.Range(0, 9).Select(a => $"order_{a}").ToArray();
18+
fsql.Aop.CommandBefore += (_, e) =>
19+
{
20+
e.Command.CommandText = Regex.Replace(e.Command.CommandText, @"/\*astable\([^\)]+\)*\/", "1=1");
21+
};
22+
}
23+
24+
public string[] AllTables { get; }
25+
26+
public string GetTableNameByColumnValue(object columnValue, bool autoExpand = false)
27+
{
28+
var modid = (int)columnValue;
29+
return $"order_{(modid % 10)}";
30+
}
31+
32+
public string[] GetTableNamesByColumnValueRange(object columnValue1, object columnValue2)
33+
{
34+
throw new NotImplementedException();
35+
}
36+
37+
public string[] GetTableNamesBySqlWhere(string sqlWhere, List<DbParameter> dbParams, SelectTableInfo tb, CommonUtils commonUtils)
38+
{
39+
var match = Regex.Match(sqlWhere, @"/\*astable\([^\)]+\)*\/");
40+
if (match.Success == false) return AllTables;
41+
var tables = match.Groups[1].Value.Split(',').Where(a => AllTables.Contains(a)).ToArray();
42+
if (tables.Any() == false) return AllTables;
43+
return tables;
44+
}
45+
}

Examples/base_entity/Program.cs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using FreeSql.Internal.CommonProvider;
77
using FreeSql.Internal.Model;
88
using FreeSql.Odbc.Default;
9+
using Microsoft.Data.SqlClient;
910
using NetTopologySuite.Geometries;
1011
using Newtonsoft.Json;
1112
using Newtonsoft.Json.Linq;
@@ -541,7 +542,7 @@ static void Main(string[] args)
541542

542543
.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")
543544

544-
//.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true")
545+
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true")
545546

546547
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2")
547548
//.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 @@ static void Main(string[] args)
576577
BaseEntity.Initialization(fsql, () => _asyncUow.Value);
577578
#endregion
578579

580+
var bulkUsers = new[] {
581+
new IdentityUser1 { Nickname = "nickname11", Username = "username11" },
582+
new IdentityUser1 { Nickname = "nickname12", Username = "username12" },
583+
new IdentityUser1 { Nickname = "nickname13", Username = "username13" },
584+
585+
new IdentityUser1 { Nickname = "nickname21", Username = "username21" },
586+
new IdentityUser1 { Nickname = "nickname22", Username = "username22" },
587+
new IdentityUser1 { Nickname = "nickname23", Username = "username23" }
588+
};
589+
fsql.Insert(bulkUsers).NoneParameter().ExecuteAffrows();
590+
bulkUsers = fsql.Select<IdentityUser1>().OrderByDescending(a => a.Id).Limit(3).ToList().ToArray();
591+
bulkUsers[0].Nickname += "_bulkupdate";
592+
bulkUsers[1].Nickname += "_bulkupdate";
593+
bulkUsers[2].Nickname += "_bulkupdate";
594+
fsql.Update<IdentityUser1>().SetSource(bulkUsers).ExecuteSqlBulkCopy();
595+
596+
579597
var objtsql1 = fsql.Select<object>().WithSql("select * from user1").ToList();
580598
var objtsql2 = fsql.Select<object>().WithSql("select * from user1").ToList<User1>();
581599

@@ -585,8 +603,8 @@ static void Main(string[] args)
585603
.ToSql();
586604

587605

588-
var table = fsql.CodeFirst.GetTableByEntity(typeof(AsTableLog));
589-
//table.SetAsTable(null, table.ColumnsByCs[nameof(AsTableLog.createtime)]);
606+
//var table = fsql.CodeFirst.GetTableByEntity(typeof(AsTableLog));
607+
//table.SetAsTable(new ModAsTableImpl(fsql), table.ColumnsByCs[nameof(AsTableLog.click)]);
590608

591609

592610
var testitems = new[]
@@ -598,9 +616,9 @@ static void Main(string[] args)
598616
new AsTableLog{ msg = "msg05", createtime = DateTime.Parse("2022-3-8 15:00:13"), click = 5 },
599617
new AsTableLog{ msg = "msg06", createtime = DateTime.Parse("2022-4-8 15:00:13"), click = 6 },
600618
new AsTableLog{ msg = "msg07", createtime = DateTime.Parse("2022-6-8 15:00:13"), click = 7 },
601-
new AsTableLog{ msg = "msg08", createtime = DateTime.Parse("2022-7-1"), click = 8},
602-
new AsTableLog{ msg = "msg09", createtime = DateTime.Parse("2022-7-1 11:00:00"), click = 8}
603-
619+
new AsTableLog{ msg = "msg08", createtime = DateTime.Parse("2022-7-1"), click = 9},
620+
new AsTableLog{ msg = "msg09", createtime = DateTime.Parse("2022-7-1 11:00:00"), click = 10},
621+
new AsTableLog{ msg = "msg10", createtime = DateTime.Parse("2022-7-1 12:00:00"), click = 10}
604622
};
605623
var sqlatb = fsql.Insert(testitems).NoneParameter();
606624
var sqlat = sqlatb.ToSql();

FreeSql.DbContext/FreeSql.DbContext.xml

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Providers/FreeSql.Provider.SqlServer/SqlServerExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public static int ExecuteSqlBulkCopy<T>(this IInsertOrUpdate<T> that, SqlBulkCop
134134
var upsert = that as InsertOrUpdateProvider<T>;
135135
if (upsert._source.Any() != true || upsert._tempPrimarys.Any() == false) return 0;
136136
var state = ExecuteSqlBulkCopyState(upsert);
137-
return UpdateProvider.ExecuteBulkUpsert(upsert, state, insert => insert.ExecuteSqlBulkCopy(copyOptions, batchSize, bulkCopyTimeout));
137+
return UpdateProvider.ExecuteBulkUpsert(upsert, state, insert => insert.ExecuteSqlBulkCopy(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout));
138138
}
139139
static NativeTuple<string, string, string, string, string[]> ExecuteSqlBulkCopyState<T>(InsertOrUpdateProvider<T> upsert) where T : class
140140
{
@@ -175,7 +175,7 @@ public static int ExecuteSqlBulkCopy<T>(this IUpdate<T> that, SqlBulkCopyOptions
175175
var update = that as UpdateProvider<T>;
176176
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0;
177177
var state = ExecuteSqlBulkCopyState(update);
178-
return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteSqlBulkCopy(copyOptions, batchSize, bulkCopyTimeout));
178+
return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteSqlBulkCopy(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout));
179179
}
180180
static NativeTuple<string, string, string, string, string[]> ExecuteSqlBulkCopyState<T>(UpdateProvider<T> update) where T : class
181181
{
@@ -309,14 +309,14 @@ public static Task<int> ExecuteSqlBulkCopyAsync<T>(this IInsertOrUpdate<T> that,
309309
var upsert = that as InsertOrUpdateProvider<T>;
310310
if (upsert._source.Any() != true || upsert._tempPrimarys.Any() == false) return Task.FromResult(0);
311311
var state = ExecuteSqlBulkCopyState(upsert);
312-
return UpdateProvider.ExecuteBulkUpsertAsync(upsert, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions, batchSize, bulkCopyTimeout, cancellationToken));
312+
return UpdateProvider.ExecuteBulkUpsertAsync(upsert, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout, cancellationToken));
313313
}
314314
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
315315
{
316316
var update = that as UpdateProvider<T>;
317317
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return Task.FromResult(0);
318318
var state = ExecuteSqlBulkCopyState(update);
319-
return UpdateProvider.ExecuteBulkUpdateAsync(update, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions, batchSize, bulkCopyTimeout, cancellationToken));
319+
return UpdateProvider.ExecuteBulkUpdateAsync(update, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions | SqlBulkCopyOptions.KeepIdentity, batchSize, bulkCopyTimeout, cancellationToken));
320320
}
321321
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
322322
{

0 commit comments

Comments
 (0)