第三十一節:批量插入框架[Zack.EFCore.Batch]和EFCore8.x自帶的批量刪除、更新

一.  說明

1. 目標

  這裏主要測試 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 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章