让我说我有一个10,000个对象的集合,我需要使用Entity Framework添加到数据库中(我认识到EF不适合这个任务,但现在让它运行它)。出于这个问题的目的,我们将做出以下假设:
IDENTITY
主键。我可以通过以下两种方式之一在Entity Framework中执行此操作:
// Option 1
foreach (var item in largeCollection)
{
_context.SomeTable.Add(item);
}
_context.SaveChanges();
// Option 2
_context.SomeTable.AddOrUpdate(largeCollection);
_context.SaveChanges();
一种方法的性能本质上是好于还是差于另一种?或者他们都转换成相同数量的单行INSERT
陈述?
换句话说,从性能的角度来看,在将多个项目插入数据库时,使用Add()
而不是AddOrUpdate()
(或反之亦然)是否有任何优势?
所以这个问题简要讨论了数据库命令方面的“更新”与“插入”之间的区别:
Cost of Inserts vs Update in SQL Server
此外,根据官方MSDN文档(https://msdn.microsoft.com/en-us/library/hh846520(v=vs.103).aspx),添加或更新执行所谓的“upsert”,这基本上是一种奇特的说法,如果存在则更新行,如果不存在则插入行。
所以现在有了这些信息,Add()
是更好的方法似乎是合乎逻辑的。此外,鉴于这个特定的应用程序最初用于填充数据库(如果我在这个假设上错了,请纠正我),看起来好像做一个AddOrUpdate()
毫无意义,因为没有什么可以更新。
最好的答案是使用AddRange。但是,Add的FAR方式比AddOrUpdate更高效。
AddOrUpdate
对每个实体执行数据库往返,以检查它是否已存在于目标表中。
因此,即使您的表为空,如果在10,000个对象上使用AddOrUpdate,也将执行10,000个数据库往返以检查数据是否存在。
加
Add方法将在更改跟踪器中添加实体,并在添加每个记录后调用DetectChanges方法。
因此,如果添加10,000个对象,则会调用DetectChanges方法10,000次,如果您有一些关系,则可能需要超过1分钟
的AddRange
AddRange方法将添加所有实体,并在添加所有实体后调用DetectChanges方法。
因此,如果添加10,000个对象,则会调用一次DetectChanges方法。
_context.SomeTable.AddRange(largeCollection);
在所有这些情况下,一旦调用SaveChanges,将执行10,000次额外的数据库往返以保存实体,这些实体也可能非常慢。
免责声明:我是Entity Framework Extensions项目的所有者
(这个图书馆不是免费的)
通过允许您一次保存多个实体,该库可以提高代码的效率。支持所有批量操作:
例:
// 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;
});