【问题标题】:Efficient way to do bulk insert/update with Entity Framework使用实体框架进行批量插入/更新的有效方法
【发布时间】:2013-06-24 11:31:18
【问题描述】:

我有一个实体列表,我想将它们插入数据库。如果实体已按原样存在于数据库中,则需要跳过它。如果它在数据库中但具有不同的值,则需要对其进行更新。

除了对每个项目进行 db 调用之外,还有其他方法吗?

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

【问题讨论】:

标签: entity-framework


【解决方案1】:

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

如果您使用的是 SQL Server,那么在您的存储过程中,请务必使用MERGE 命令,它可以有效地完全完成您需要的操作:如果不存在则插入,如果不存在则更新确实如此。一切尽在一个高效的 SQL 查询中。

【讨论】:

  • 如果使用 SqlBulkCopy,它不能全部在一个查询中。它需要一个 sp 来创建临时表,然后是一个 sp 来与中间的 .net 内容进行合并。
  • @IanWarburton 为什么需要SqlBulkCopy? SQL Merge 命令可以满足您的所有需求。您可以通过将实体作为参数(例如表值参数)传递来调用存储过程,Merge 将完成所有工作。
  • 我让它工作了,但现在他们说它需要在 SQL Server 2000 上运行。有什么想法吗?
  • Urrghhhhhh 我讨厌这是答案。
  • 现在您已经将代码与特定的数据库实现紧密耦合。
【解决方案2】:

EF 不适合 BULK 插入。 对于 1000 条记录来说还可以,但大量(超过 10 万条)记录速度很慢。

如果您打算使用 EF。

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

例如

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

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

【讨论】:

  • 我觉得如果一个batch中间出现唯一约束异常会很尴尬。
  • 如果你可能有很多独特的约束违规,批量提交确实没那么有用。实际上,关于保存数据包的评论是建议您将它们保持小,最大 1000 不太大。 Ef 不能很好地应付饱腹感。如果吞吐量正常,请使用单记录提交。您还可以尝试使用较小的数据包,例如 10,如果失败,则为失败的数据包重试单个记录。只是我试图获得更好的吞吐量的各种事情。
【解决方案3】:

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

而且使用起来真的很简单

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

【讨论】:

  • 请注意:这个库不支持导航属性。如果您有父子表关联,则插入后您的子表元素的外键将设置为 0
  • 这不处理更新方面的事情。
  • 免费吗?或者我需要付钱吗?。和这个entityframework-extensions.net/#pro一样吗?
  • @AlejandroMosquera 如果你愿意,可以付钱给我 :D,但它是免费和开源的
  • @maxlego 谢谢。
【解决方案4】:
  1. 创建临时表: SqlCommand(string.Format("SELECT TOP 0 * INTO {0} FROM {1}...

  2. 向其中批量插入数据 -- 上面提到的 Entity Framework Extended 需要进行调整以支持临时表名称,但其他方面都在正确的轨道上 -- 或者滚动一些代码并使用 SqlBulkCopy。

  3. 构造一个 MERGE 语句。

如果您挖掘属性列表,您可以将 (2) 和 (3) 设为通用。我可以在大约 20 秒内读取和合并 150,000 行。

【讨论】:

    猜你喜欢
    • 2014-07-12
    • 2015-06-22
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 2018-12-03
    相关资源
    最近更新 更多