26

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

除了对每个项目进行 db 调用之外,还有什么方法可以做到这一点?

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

4

4 回答 4

25

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

如果您使用的是 SQL Server,那么在您的存储过程中,请使用MERGE能够有效执行您需要的命令如果不存在则插入,如果存在则更新。一切尽在一个高效的 SQL 查询中。

于 2013-06-24T11:52:24.627 回答
11

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

如果您打算使用 EF。

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

例如

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

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

于 2013-06-24T11:47:00.337 回答
9

我已经为该 https://efbulkinsert.codeplex.com/进行了扩展

而且使用起来非常简单

using(var context = new MyDbContext())
{
    context.BulkInsert(hugeCollectionOfEntities);
}
于 2014-02-11T21:12:04.910 回答
1
  1. 创建一个临时表: SqlCommand(string.Format("SELECT TOP 0 * INTO {0} FROM {1}...

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

  3. 构造一个 MERGE 语句。

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

于 2015-06-04T04:42:10.590 回答