实体框架:AddOrUpdate() 与循环 Add() 的性能

Ari*_*oth 1 c# entity-framework

假设我有一个包含 10,000 个对象的集合,需要使用实体框架将其添加到数据库中(我认识到 EF 不太适合此任务,但现在让我们运行它)。出于本问题的目的,我们将做出以下假设:

  1. 只有一张表,有一个IDENTITY主键。
  2. 桌子是空的。
  3. 对象很简单——一切都是原始数据类型(int、bool、string 等)

我可以通过以下两种方式之一在实体框架中执行此操作:

// Option 1
foreach (var item in largeCollection)
{
    _context.SomeTable.Add(item);
}

_context.SaveChanges();

// Option 2
_context.SomeTable.AddOrUpdate(largeCollection);
_context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

一种方法的性能本质上比另一种方法更好还是更差?或者它们都转化为相同数量的单行INSERT语句?

换句话说,从性能的角度来看,在将多个项目插入数据库时​​使用Add()over AddOrUpdate()(或反之亦然)是否有任何优势?

Jon*_*nan 5

最好的答案是使用 AddRange。然而,Add 的性能远远高于 AddOrUpdate。

添加或更新

对每个实体执行数据库往返,以检查它是否已存在于目标表中。

因此,即使您的表为空,如果您对 10,000 个对象使用 AddOrUpdate,也会执行 10,000 次数据库往返来检查数据是否存在。

添加

Add 方法将在更改跟踪器中添加一个实体,并在添加每条记录后调用 DetectChanges 方法。

因此,如果添加 10,000 个对象,则 DetectChanges 方法将被调用 10,000 次,如果您有几个关系,则可能需要 1 分钟以上

请参阅:性能添加

添加范围

AddRange 方法将添加所有实体,并在添加所有实体后调用 DetectChanges 方法。

因此,如果添加 10,000 个对象,则 DetectChanges 方法将被调用一次。

_context.SomeTable.AddRange(largeCollection);
Run Code Online (Sandbox Code Playgroud)

在所有这种情况下,一旦调用 SaveChanges,将执行 10,000 次额外的数据库往返来保存实体,这也可能非常慢。

免责声明:我是实体框架扩展项目的所有者

(这个库不是免费的)

该库允许您一次保存多个实体,从而使您的代码更加高效。支持所有批量操作:

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

例子:

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

// Customize Primary Key
context.BulkMerge(customers, operation => {
   operation.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});
Run Code Online (Sandbox Code Playgroud)