第三十一节:批量插入框架[Zack.EFCore.Batch]和EFCore8.x自带的批量删除、更新
一. 说明
这里主要测试 EFCore8.x 版本提供的批量删除 和 批量更新; 以及老杨的框架 [Zack.EFCore.Batch]
以SQLServer为载体进行测试。
2. 准备
(1). 需要的程序集
必须的程序集: Microsoft.EntityFrameworkCore.Tools
EF自身的程序集: Microsoft.EntityFrameworkCore.SqlServer
PS:【Microsoft.EntityFrameworkCore.SqlServer】:用来连接SQLServer数据库,里面包含【Microsoft.EntityFrameworkCore.Relational】,而它里面又包含:【Microsoft.EntityFrameworkCore】
(2). 常用指令
A.全表的首次映射:
【Scaffold-DbContext "Server=localhost;Database=EFCore6xDB;User ID=sa;Password=123456;Encrypt=true;TrustServerCertificate=true;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Context EFCore8xDBContext -UseDatabaseNames -DataAnnotations -NoPluralize】
特别注意:
① 需要加上 Encrypt=true;TrustServerCertificate=true; 否则映射会报证书错误 (Encrypt=true; 可以不加)
② 个人倾向注释掉 <Nullable>enable</Nullable> 再生成
二. 批量插入框架
1. 说明
该组件对于EF8.x仅支持批量插入操作了,批量更新、批量删除已经删除,推荐使用官方EF8.x提供的
下面以SQLServer来测试
注:On mysql, to use BulkInsert, please enable local_infile on server side and client side: enable "local_infile=ON" on mysql server,and add "AllowLoadLocalInfile=true" to connection string on client side.
支持三种数据库:
SQLServer: Install-Package Zack.EFCore.Batch.MSSQL_NET8
MySQL: Install-Package Zack.EFCore.Batch.MySQL.Pomelo_NET8
Postgresql: Install-Package Zack.EFCore.Batch.Npgsql_NET8
注:
在 mysql中, 如果使用BulkInsert,请在服务器端和客户端都启用local_infile:在mysql server服务器端
启用"local_infile=ON",然后在连接字符串中添加 "AllowLoadLocalInfile=true"。
2. 实操
(1). 通过Nuget安装程序集 【Zack.EFCore.Batch.MSSQL_NET8】
(2). 不需要在 OnConfiguring中做任何配置了
(3). 调用BulkInsert方法批量插入即可
{
var userList = new List<UserInfo>();
for (int i = 0; i < 10000; i++)
{
userList.Add(new UserInfo()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf" + i,
userPwd = "test" + i,
userGender = "男",
userAge = i,
addTime = DateTime.Now,
delflag = 0
});
}
var db = new EFCore7xDBContext();
db.BulkInsert(userList);
Console.WriteLine("插入成功");
}
3. 性能测试
10w条数据,使用官方的AddRange() 大约21s,使用该框架大约 5s
三. 批量删除、更新
1. 说明
删除:使用EFCore8.x自定的 ExecuteDelete 或 ExecuteDeleteAsync 方法
更新:使用EFCore8.x自定的 ExecuteUpdate 或 ExecuteUpdateAsync 方法
2. 批量删除实操
详见代码
{
var db = new EFCore8xDBContext();
var count = db.UserInfo.Where(u => u.userName.Contains("2")).ExecuteDelete();
Console.WriteLine($"删除了{count}条数据");
}
生成SQL语句如图1
3. 批量更新实操
详见代码
{
var db = new EFCore8xDBContext();
var count = db.UserInfo.Where(u => u.userName.EndsWith("3"))
.ExecuteUpdate(u => u.SetProperty(u => u.userPwd, "123456")
.SetProperty(u => u.userAge, u => u.userAge + 100000)
);
Console.WriteLine($"删除了{count}条数据");
}
生成SQL语句如图2
4. 事务操作
批量插入不能放到事务中,直接报错,Unexpected existing transaction
批量更新和批量删除可以放到事务中
查看代码
{
using var db = new EFCore8xDBContext();
using (var transaction = db.Database.BeginTransaction())
{
try
{
//1. 批量插入【不能放到事务里,直接报错,Unexpected existing transaction.】
//List<UserInfo> userList = new();
//for (int i = 1; i <= 4; i++)
//{
// UserInfo user = new UserInfo()
// {
// id = Guid.NewGuid().ToString("N"),
// userName = "ypf1_" + i,
// userPwd = "123456",
// userAge = 19,
// userGender = "男",
// addTime = DateTime.Now,
// delflag = 0
// };
// userList.Add(user);
//}
//await db.BulkInsertAsync(userList);
//2-批量删除【可以放到事务里】
var count1 = db.UserInfo.Where(u => u.userName.Contains("2")).ExecuteDelete();
//3. 批量修改 【可以放到事务里】
var count2 = db.UserInfo.Where(u => u.userName.EndsWith("3"))
.ExecuteUpdate(u => u.SetProperty(u => u.userPwd, "123456")
.SetProperty(u => u.userAge, u => u.userAge + 100000)
);
//4. 模拟错误
UserInfo user2 = new()
{
id = Guid.NewGuid().ToString("N") + "354545", //模拟错误
userName = "ypf2_",
userPwd = "123456",
userAge = 19,
userGender = "男",
addTime = DateTime.Now,
delflag = 0
};
db.Add(user2);
db.SaveChanges();
//最终事务提交
transaction.Commit();
Console.WriteLine("操作成功");
}
catch (Exception ex)
{
//using包裹不需要手写rollback
Console.WriteLine("错误为:" + ex.Message);
}
}
}
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。