FreeSql支持丰富的更新数据方法,支持单条或批量更新,在特定的数据库执行还可以返回更新后的记录值。
var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" +
"Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10";
IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.MySql, connstr)
.UseAutoSyncStructure(true) //自动同步实体结构到数据库
.Build();
[Table(Name = "tb_topic")]
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();
for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 });
fsql.Update().SetSource(items).ExecuteAffrows();
//UPDATE `tb_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))
批量更新的场景,先查询20条记录,根据本地很复杂的规则把集合的值改完后
传统做法是循环20次保存,用 case when 只要一次就行
批量更新,忽略一些列
fsql.Update().SetSource(items).IgnoreColumns(a => new { a.Clicks, a.CreateTime }).ExecuteAffrows();
//UPDATE `tb_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().SetSource(items).Set(a => a.CreateTime, DateTime.Now).ExecuteAffrows();
//UPDATE `tb_topic` SET `CreateTime` = ?p_0 WHERE (`Id` IN (1,2,3,4,5,6,7,8,9,10))
指定列更新后,批量保存将失效
内部实现
当更新大批量数据时,内部采用分割分批执行的逻辑进行。分割规则如下:
数量 | 参数量 | |
---|---|---|
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 | T1 | IEnumerable | 更新数据,设置更新的实体 | |
IgnoreColumns | Lambda | 忽略的列 | |
Set | Lambda, value | 设置列的新值,Set(a => a.Name, "newvalue") | |
Set | Lambda | 设置列的的新值为基础上增加,Set(a => a.Clicks + 1),相当于 clicks=clicks+1; | |
SetRaw | string, parms | 设置值,自定义SQL语法,SetRaw("title = ?title", new { title = "newtitle" }) | |
Where | Lambda | 表达式条件,仅支持实体基础成员(不包含导航对象) | |
Where | string, parms | 原生sql语法条件,Where("id = ?id", new { id = 1 }) | |
Where | T1 | IEnumerable | 传入实体或集合,将其主键作为条件 | |
WhereExists | ISelect | 子查询是否存在 | |
WithTransaction | DbTransaction | 设置事务对象 | |
ToSql | string | 返回即将执行的SQL语句 | |
ExecuteAffrows | long | 执行SQL语句,返回影响的行数 | |
ExecuteUpdated | List |
执行SQL语句,返回更新后的记录 |
系列文章导航
(一)入门
(二)自动迁移实体
(三)实体特性
(四)实体特性 Fluent Api
(五)插入数据
(六)批量插入数据
(七)插入数据时忽略列
(八)插入数据时指定列
(九)删除数据
(十)更新数据
(十一)更新数据 Where
(十二)更新数据时指定列
(十三)更新数据时忽略列
(十四)批量更新数据
(十五)查询数据
(十六)分页查询
(十七)联表查询
(十八)导航属性
(十九)多表查询
(二十)多表查询 WhereCascade
(二十一)查询返回数据
(二十二)Dto 映射查询
(二十三)分组、聚合
(二十四)Linq To Sql 语法使用介绍
(二十五)延时加载
(二十六)贪婪加载 Include、IncludeMany、Dto、ToList
(二十七)将已写好的 SQL 语句,与实体类映射进行二次查询
(二十八)事务
(二十九)Lambda 表达式
(三十)读写分离
(三十一)分区分表
(三十二)Aop
(三十三)CodeFirst 类型映射
(三十四)CodeFirst 迁移说明
(三十五)CodeFirst 自定义特性