【问题标题】:How to do bulk update in EF Core?如何在 EF Core 中进行批量更新?
【发布时间】:2021-02-25 07:23:00
【问题描述】:

我正在尝试使用 EF Core 进行批量更新。

如何在 EF Core 中为此处显示的 SQL 语句编写代码?

Update Students 
Set RollNum = 1, 
    Email = 'hsdjasjhd@gmail.com', 
    FirstName = 'Ramamkagja'
Where Id in (428, 442, 444, 445, 448, 450, 458, 460)

【问题讨论】:

    标签: c# .net entity-framework entity-framework-core


    【解决方案1】:

    你可以使用 DbContext.UpdateRange 方法

    例子

    using (YourDbContext context = new YourDbContext())
    {
        List<Student> students = new List<Student>()
            {
            new Student(){Id=428, Email="hsdjasjhd@gmail.com"},
            new Student(){Id=442, Email="hsdjasjhd@gmail.com"},
            new Student(){Id=444, Email="hsdjasjhd@gmail.com"}
            // Add Full Properties and remaining students here
            };
                                    
        context.Students.UpdateRange(students);
        context.SaveChanges();
    }
    

    确保学生 ID 存在于数据库中

    【讨论】:

      【解决方案2】:

      免责声明:我是项目的所有者Entity Framework Plus

      您正在寻找“批量更新”功能:https://entityframework-plus.net/ef-core-batch-update

      例子:

      var ids = new List<int>() { 428, 442, 444, 445, 448, 450, 458, 460 };
      ctx.Students.Where(x => ids.Contains(x.Id))
               .Update(x => new Student() { Email = "hsdjasjhd@gmail.com", FirstName = "Ramamkagja" });
      

      一切都将在数据库端执行,因此您不必在上下文中加载现有学生。

      【讨论】:

        【解决方案3】:

        您可以有多个选项来更新实体框架核心中的批量。 UpdateRange 从版本 1 开始可用。因此您可以使用该方法更新所有条目,如下所示:

        using (dbContext context = new dbContext())
        {
            var entities = new List<Student>()
                {
                new Student(){Id=8, Email="test1@gmail.com"},
                new Student(){Id=2, Email="test2@gmail.com"},
                new Student(){Id=4, Email="test3@gmail.com"}        
                };
                                        
            context.Students.UpdateRange(students);
            context.SaveChanges();
        }
        

        为了获得更好的性能,我更喜欢的第二种方法是使用存储过程/或原始 SQL 查询并使用 efcore 从您的代码中调用它。 如下:

        string query = "Set RollNum = 1, Email = 'hsdjasjhd@gmail.com', FirstName = 'Ramamkagja' Where Id in (428, 442, 444, 445, 448, 450, 458, 460);    
         context.Database.ExecuteSqlCommand(query);
        

        参考资料:

        Execute Sql Command

        Update Range

        【讨论】:

          【解决方案4】:

          如果您有 IQueryable,那么 Entity Framework Core 5.0 中引入的 IQueryable.ToQueryString 方法可能会有所帮助。此方法将生成可包含在原始 SQL 查询中的 SQL,以对该查询标识的记录执行批量更新。

          例如:

          using var context = new DbContext();
          
          var ids = new List<int>() { 428, 442, 444, 445, 448, 450, 458, 460 };
          
          var query = context.Students.Where(_ => ids.Contains(_.Id)).Select(_ => _.Id);
          
          var sql = $@"
          UPDATE Students
          SET RollNum = {{0}}, Email = {{1}}, FirstName = {{2}}
          WHERE Id IN ({query.ToQueryString()})
          ";
          
          context.Database.ExecuteSqlRaw(sql, 1, "hsdjasjhd@gmail.com", "Ramamkagja");
          

          这种方法的主要缺点是最终会在代码中出现原始 SQL。但是,我不知道有任何合理的方法可以通过当前的 Entity Framework Core 功能来避免这种情况 - 您被这个警告或此处发布的其他答案的警告所困扰,例如:

          • 引入对另一个库的依赖,例如 Entity Framework Plus
          • 使用 DbContext.SaveChanges() 一次更新一条记录,而不是进行批量更新。

          【讨论】:

            猜你喜欢
            • 2014-10-30
            • 1970-01-01
            • 2018-04-01
            • 2020-07-10
            • 1970-01-01
            • 1970-01-01
            • 2011-02-24
            • 2016-09-21
            • 2018-04-09
            相关资源
            最近更新 更多