实体框架的大批量更新比我自己批量更新慢得多

Posted

技术标签:

【中文标题】实体框架的大批量更新比我自己批量更新慢得多【英文标题】:Big Batch of Entity Framework Updates Much Slower Than Batching Myself 【发布时间】:2018-07-30 00:01:09 【问题描述】:

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

当我记录实体框架的数据库活动时,我看到它正在生成与我自己生成的相同的基本查询,但它似乎一次运行它们而不是一次运行它们,即使我只调用 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"));

【问题讨论】:

这里有问题吗? 速度慢的是网络和数据库之间的接口。使用 linq 方法更快。 ExecuteSqlCommand 是慢速方法。您应该能够在“资源”对象上使用 linq 以获得相同的结果。 看来EF不能批量更新。你可以试试 EF Core 吗?其中一项新功能是能够进行批量更新。 @jdweng 如果您有一个示例,说明 linq 方法如何在给定我上面的用例之类的情况下更快,请作为答案发布,我很乐意尝试一下。跨度> @kirchner 在短期内我不能使用 EF Core。我确实看到该功能已添加到 EF Core,因此我会牢记这一点以备不时之需。感谢您让我知道。 【参考方案1】:

正如@EricEJ 和@Kirchner 报告的那样,EF6 不支持批量更新。但是,一些第三方库会这样做。


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

EF+ 批量更新允许使用相同的值/公式更新多行。

例如:

context.Resources
    .Where(x => resourceIds.Contains(x => x.ResourceId)
    .Update(x => new Resource()  IsBlank = false );

由于实体未在上下文中加载,因此您应该获得最佳性能。

阅读更多:http://entityframework-plus.net/batch-update


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

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

批量保存更改 批量插入 批量删除 批量更新 批量合并

例如:

// 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);

【讨论】:

【参考方案2】:

Entity Framework 6 不支持批处理,EF Core 支持

【讨论】:

以上是关于实体框架的大批量更新比我自己批量更新慢得多的主要内容,如果未能解决你的问题,请参考以下文章

批量更新/删除EF5

如何强制实体框架始终从数据库中获取更新数据?

核心数据批量更新

批量更新表行,同时重新排序和更新?

使用实体框架更新语句

批量更新记录