【发布时间】:2013-06-24 11:31:18
【问题描述】:
我有一个实体列表,我想将它们插入数据库。如果实体已按原样存在于数据库中,则需要跳过它。如果它在数据库中但具有不同的值,则需要对其进行更新。
除了对每个项目进行 db 调用之外,还有其他方法吗?
我的计划是尝试插入,如果键上的唯一约束异常被抛出然后进行更新。
【问题讨论】:
-
Telerik DataAccess 可以进行批量更新
标签: entity-framework
我有一个实体列表,我想将它们插入数据库。如果实体已按原样存在于数据库中,则需要跳过它。如果它在数据库中但具有不同的值,则需要对其进行更新。
除了对每个项目进行 db 调用之外,还有其他方法吗?
我的计划是尝试插入,如果键上的唯一约束异常被抛出然后进行更新。
【问题讨论】:
标签: entity-framework
在这种情况下不要使用实体框架。只需使用存储过程(如何使用取决于您在 EF 中使用的版本/方法,您可能需要扩展您的 DbContext 或从实体模型添加映射)。
如果您使用的是 SQL Server,那么在您的存储过程中,请务必使用MERGE 命令,它可以有效地完全完成您需要的操作:如果不存在则插入,如果不存在则更新确实如此。一切尽在一个高效的 SQL 查询中。
【讨论】:
SqlBulkCopy? SQL Merge 命令可以满足您的所有需求。您可以通过将实体作为参数(例如表值参数)传递来调用存储过程,Merge 将完成所有工作。
EF 不适合 BULK 插入。 对于 1000 条记录来说还可以,但大量(超过 10 万条)记录速度很慢。
如果您打算使用 EF。
例如
Context.Set<TPoco>().AddOrUpdate(poco);
//...
Context.Configuration.AutoDetectChangesEnabled =
//..
Context.SaveChanges();
如果复制不相关的数据,您可以并行尝试这些表 (doh)
【讨论】:
我为此做了一个扩展 https://efbulkinsert.codeplex.com/
而且使用起来真的很简单
using(var context = new MyDbContext())
{
context.BulkInsert(hugeCollectionOfEntities);
}
【讨论】:
创建临时表: SqlCommand(string.Format("SELECT TOP 0 * INTO {0} FROM {1}...
向其中批量插入数据 -- 上面提到的 Entity Framework Extended 需要进行调整以支持临时表名称,但其他方面都在正确的轨道上 -- 或者滚动一些代码并使用 SqlBulkCopy。
构造一个 MERGE 语句。
如果您挖掘属性列表,您可以将 (2) 和 (3) 设为通用。我可以在大约 20 秒内读取和合并 150,000 行。
【讨论】: