C# 大批量实体框架更新要比批量更新慢得多

C# 大批量实体框架更新要比批量更新慢得多,c#,sql,sql-server,entity-framework,C#,Sql,Sql Server,Entity Framework,使用我认为是标准的实体框架技术更新一堆记录要比批处理自己生成的相同查询慢得多。对于250条记录,我看到实体框架的速度是它的10倍。对于1000条记录,速度会慢20倍左右 当我记录entity framework的数据库活动时,我看到它正在生成与我自己生成的基本查询相同的查询,但它似乎一次只运行一个查询,而不是一次运行所有查询,即使我只调用一次SaveChanges。有没有办法让它一次运行所有查询 我不能进行简单的大规模SQL更新,因为在我的实际用例中,每一行都需要单独处理,以确定字段的设置 示例

使用我认为是标准的实体框架技术更新一堆记录要比批处理自己生成的相同查询慢得多。对于250条记录,我看到实体框架的速度是它的10倍。对于1000条记录,速度会慢20倍左右

当我记录entity framework的数据库活动时,我看到它正在生成与我自己生成的基本查询相同的查询,但它似乎一次只运行一个查询,而不是一次运行所有查询,即使我只调用一次SaveChanges。有没有办法让它一次运行所有查询

我不能进行简单的大规模SQL更新,因为在我的实际用例中,每一行都需要单独处理,以确定字段的设置

示例定时代码如下所示:

var stopwatchEntity = new System.Diagnostics.Stopwatch();
var stopwatchUpdate = new System.Diagnostics.Stopwatch();
using (var dbo = new ProjDb.dbo("Server=server;Database=database;Trusted_Connection=True;"))
{
    var resourceIds = dbo.Resources.Select(r => r.ResourceId).Take(250).ToList();

    //dbo.Database.Log += (s) => System.Diagnostics.Debug.WriteLine(s);

    stopwatchEntity.Start();
    foreach (var resourceId in resourceIds)
    {
        var resource = new ProjDb.Models.dbo.Resource { ResourceId = resourceId };
        dbo.Resources.Attach(resource);
        resource.IsBlank = false;
    }
    dbo.SaveChanges();
    stopwatchEntity.Stop();

    stopwatchUpdate.Start();
    var updateStr = "";
    foreach (var resourceId in resourceIds)
        updateStr += "UPDATE Resources SET IsBlank = 0 WHERE ResourceId = " + resourceId + ";";
    dbo.Database.ExecuteSqlCommand(updateStr);
    stopwatchUpdate.Stop();

    MessageBox.Show(stopwatchEntity.Elapsed.TotalSeconds.ToString("f") + ", " + stopwatchUpdate.Elapsed.TotalSeconds.ToString("f"));
}

实体框架6不支持批处理,EF Core不支持批处理,正如@EricEJ和@Kirchner报告的那样,EF6不支持批处理更新。但是,有些第三方库会这样做


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

EF+批量更新允许更新具有相同值/公式的多行

例如:

context.Resources
    .Where(x => resourceIds.Contains(x => x.ResourceId)
    .Update(x => new Resource() { IsBlank = false });
// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);
context.BulkMerge(customers);
由于没有在上下文中加载实体,因此应该获得最佳的可用性能

阅读更多:


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

如果行与行之间的值必须不同,则此库允许
BulkUpdate
功能。此库是一个付费库,但几乎支持性能所需的一切:

  • 批量保存更改
  • 批量插入
  • 批量删除
  • 批量更新
  • 批量合并
例如:

context.Resources
    .Where(x => resourceIds.Contains(x => x.ResourceId)
    .Update(x => new Resource() { IsBlank = false });
// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);
context.BulkMerge(customers);

这里有一个问题吗?网络和数据库之间的接口使事情变慢了。使用linq方法更快。ExecuteSqlCommand是一种慢方法。您应该能够在“资源”对象上使用linq来获得相同的结果。似乎EF无法批量更新。你能试试EF Core吗?新功能之一是批量更新的能力。@jdweng如果您有一个例子,说明linq方法如何在上面的用例中更快,请作为答案发布,我很乐意尝试一下。@kirchner短期内我不能使用EF Core。我确实看到EF Core中添加了该功能,因此我将在将来记住它。谢谢你让我知道这件事。