使用Entity Framework进行批量插入/更新的有效方法

时间:2013-06-24 11:31:18

标签: entity-framework

我有一个实体列表,我想将它们插入到数据库中。如果实体已经存在于数据库中,则需要跳过该实体。如果它在数据库中但具有不同的值,那么它需要更新。

除了为每个项目执行db调用之外,还有什么办法吗?

我的计划是尝试插入,如果抛出了键上的唯一约束异常,则进行更新。

4 个答案:

答案 0 :(得分:24)

在这种情况下不要使用实体框架。只需使用存储过程(如何依赖于您使用EF的版本/方法,您可能必须扩展您的DbContext或从实体模型添加映射。)

如果您正在使用SQL Server,那么在您的商店程序中,请使用有效完全所需内容的MERGE命令:如果不存在则插入,或者更新,如果它。所有内容都在一个高效的SQL查询中。

答案 1 :(得分:10)

EF不适合BULK刀片。 对于1000个记录来说还可以,但是大数(100k以上)它的速度很慢。

如果您打算使用EF。

  • 尝试AddOrUpdate方法,(而不是插入/更新)
  • 禁用跟踪,
  • 每1000条或更少的记录提交。

例如

Context.Set<TPoco>().AddOrUpdate(poco);
//...
Context.Configuration.AutoDetectChangesEnabled =
//..
Context.SaveChanges();

如果复制不相关的数据,您可以并行尝试这些表(doh)

答案 2 :(得分:9)

我为此做了一个扩展 https://efbulkinsert.codeplex.com/

使用起来非常简单

using(var context = new MyDbContext())
{
    context.BulkInsert(hugeCollectionOfEntities);
}

答案 3 :(得分:1)

  1. 创建临时表: SqlCommand(string.Format(&#34; SELECT TOP 0 * INTO {0} FROM {1} ...

  2. 批量插入数据 - 上面提到的实体框架扩展需要调整以支持临时表名称,否则就是在正确的轨道上 - 或者滚动一些代码并使用SqlBulkCopy。

  3. 构建MERGE语句。

  4. 如果你挖掘一个属性列表,你可以使(2)和(3)通用。我可以在大约20秒内读取并合并150,000行。