第三十一节:批量插入框架[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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2024-04-16 10:46  Yaopengfei  阅读(225)  评论(0编辑  收藏  举报