FreeSql (十四)批量更新数据
static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.MySql, connectionString)
.UseAutoSyncStructure(true) //自动同步实体结构到数据库
.Build(); //请务必定义成 Singleton 单例模式
class Topic {
[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; }
}
批量更新
var items = new List<Topic>();
for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 });
var t6 = fsql.Update<Topic>().SetSource(items).ExecuteAffrows();
//UPDATE `Topic` SET `Clicks` = CASE `Id` WHEN 1 THEN @p_0 WHEN 2 THEN @p_1 WHEN 3 THEN @p_2 WHEN 4 THEN @p_3 WHEN 5 THEN @p_4 WHEN 6 THEN @p_5 WHEN 7 THEN @p_6 WHEN 8 THEN @p_7 WHEN 9 THEN @p_8 WHEN 10 THEN @p_9 END,
//`Title` = CASE `Id` WHEN 1 THEN @p_10 WHEN 2 THEN @p_11 WHEN 3 THEN @p_12 WHEN 4 THEN @p_13 WHEN 5 THEN @p_14 WHEN 6 THEN @p_15 WHEN 7 THEN @p_16 WHEN 8 THEN @p_17 WHEN 9 THEN @p_18 WHEN 10 THEN @p_19 END,
//`CreateTime` = CASE `Id` WHEN 1 THEN @p_20 WHEN 2 THEN @p_21 WHEN 3 THEN @p_22 WHEN 4 THEN @p_23 WHEN 5 THEN @p_24 WHEN 6 THEN @p_25 WHEN 7 THEN @p_26 WHEN 8 THEN @p_27 WHEN 9 THEN @p_28 WHEN 10 THEN @p_29 END
//WHERE (`Id` IN (1,2,3,4,5,6,7,8,9,10))
批量更新的场景,先查询10条记录,根据本地很复杂的规则把集合的值改完后
传统做法是循环10次保存,用 case when 只要一次就行
批量更新,忽略一些列
fsql.Update<Topic>().SetSource(items).IgnoreColumns(a => new { a.Clicks, a.CreateTime }).ExecuteAffrows();
//UPDATE `Topic` SET `Title` = CASE `Id` WHEN 1 THEN @p_0 WHEN 2 THEN @p_1 WHEN 3 THEN @p_2 WHEN 4 THEN @p_3 WHEN 5 THEN @p_4 WHEN 6 THEN @p_5 WHEN 7 THEN @p_6 WHEN 8 THEN @p_7 WHEN 9 THEN @p_8 WHEN 10 THEN @p_9 END
//WHERE (`Id` IN (1,2,3,4,5,6,7,8,9,10))
批量更新指定列
fsql.Update<Topic>()
.SetSource(items)
.Set(a => a.CreateTime, DateTime.Now)
.ExecuteAffrows();
//UPDATE `Topic` SET `CreateTime` = @p_0
//WHERE (`Id` IN (1,2,3,4,5,6,7,8,9,10))
指定 Set 列更新后,SetSource 将失效
内部实现
当更新大批量数据时,内部采用分割分批执行的逻辑进行。分割规则如下:
数量 | 参数量 | |
---|---|---|
MySql | 5000 | 3000 |
PostgreSQL | 5000 | 3000 |
SqlServer | 1000 | 2100 |
Oracle | 500 | 999 |
Sqlite | 5000 | 999 |
数据:为每批分割的大小,如批量插入 10000 条数据,在 mysql 执行时会分割为两批。
参数量:为每批分割的参数量大小,如批量插入 10000 条数据,每行需要使用 5 个参数化,在 mysql 执行时会分割为每批 3000 / 5。
分割执行后,当外部未提供事务时,内部自开事务,实现插入完整性。
FreeSql 适配了每一种数据类型参数化,和不参数化的使用。批量插入建议关闭参数化功能,使用 .NonoParameter() 进行执行。
API
方法 | 返回值 | 参数 | 描述 |
---|---|---|---|
SetSource | <this> | T1 | IEnumerable |
更新数据,设置更新的实体 |
IgnoreColumns | <this> | Lambda | 忽略的列 |
Set | <this> | Lambda, value | 设置列的新值,Set(a => a.Name, "newvalue") |
Set | <this> | Lambda | 设置列的的新值为基础上增加,Set(a => a.Clicks + 1),相当于 clicks=clicks+1 |
SetDto | <this> | object | 根据 dto 更新的方法 |
SetRaw | <this> | string, parms | 设置值,自定义SQL语法,SetRaw("title = @title", new { title = "newtitle" }) |
Where | <this> | Lambda | 表达式条件,仅支持实体基础成员(不包含导航对象) |
Where | <this> | string, parms | 原生sql语法条件,Where("id = @id", new { id = 1 }) |
Where | <this> | T1 | IEnumerable |
传入实体或集合,将其主键作为条件 |
WhereExists | <this> | ISelect | 子查询是否存在 |
CommandTimeout | <this> | int | 命令超时设置(秒) |
WithTransaction | <this> | DbTransaction | 设置事务对象 |
WithConnection | <this> | DbConnection | 设置连接对象 |
ToSql | string | 返回即将执行的SQL语句 | |
ExecuteAffrows | long | 执行SQL语句,返回影响的行数 | |
ExecuteUpdated | List<T1> | 执行SQL语句,返回更新后的记录 |
系列文章导航
-
(十四)批量更新数据