一. 說明
這裏主要測試 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 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。