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

时间:2018-02-19 17:40:38

标签: c# sql sql-server entity-framework

使用我认为的标准实体框架技术更新一堆记录比使用自己生成的相同查询批处理要慢得多。对于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"));
}

2 个答案:

答案 0 :(得分:3)

正如@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);

答案 1 :(得分:1)

实体框架6不支持批处理,EF Core支持