我有一个实体列表,我想将它们插入到数据库中。如果实体已经存在于数据库中,那么它需要被跳过。如果它在数据库中但具有不同的值,则需要更新它。使用实体框架进行批量插入/更新的有效方法
有没有办法做到这一点,而不是每个项目做一个数据库调用?
我的计划是尝试一个插入,如果一个唯一的约束异常的关键是抛出然后做一个更新。
我有一个实体列表,我想将它们插入到数据库中。如果实体已经存在于数据库中,那么它需要被跳过。如果它在数据库中但具有不同的值,则需要更新它。使用实体框架进行批量插入/更新的有效方法
有没有办法做到这一点,而不是每个项目做一个数据库调用?
我的计划是尝试一个插入,如果一个唯一的约束异常的关键是抛出然后做一个更新。
只是不要在这种情况下使用实体框架。只需使用存储过程(如何取决于您使用EF的版本/方法,您可能需要扩展您的DbContext
或添加实体模型的映射)。
如果您使用的SQL Server,然后在你的存储过程,使用该MERGE
命令有效不正是你需要:insert,如果它不存在,或者更新,如果它。一切都在一个高效的SQL查询中。
如果使用SqlBulkCopy,它不能全部在单个查询中。它需要是一个sp来创建临时表,然后是一个sp来完成与中间的.net内容的合并。 –
@IanWarburton为什么你需要'SqlBulkCopy'? SQL'Merge'命令可以满足您的所有需求。你可以通过传递你的实体作为参数来调用一个存储过程(例如表值参数),'Merge'将完成所有的工作。 – ken2k
表值参数...是很酷。 –
EF不适用于BULK插页。 对于1000年的记录它可以,但大数字(100k加)它的速度慢。
如果您打算使用EF。
如
Context.Set<TPoco>().AddOrUpdate(poco);
//...
Context.Configuration.AutoDetectChangesEnabled =
//..
Context.SaveChanges();
如果复制无关的数据,你可以尝试在平行(DOH)这些表
我认为如果在批处理中存在唯一的约束异常,那将会很尴尬。 –
如果您可能有许多独特的约束违规,那么批量提交的确不太有用。其实关于保存数据包的评论是建议你保持它们小,最大1000不太大。如果没有完整的腹部应付。如果吞吐量正常,请使用单个记录提交。您还可以尝试使用较小的数据包,例如10个,如果失败,则重试单个数据包。只是各种事情,我试图获得更好的吞吐量。 –
我已经为 https://efbulkinsert.codeplex.com/
的延伸,它是非常简单的使用
using(var context = new MyDbContext())
{
context.BulkInsert(hugeCollectionOfEntities);
}
只是抬头:这个库不支持导航属性。如果您有父/子表关联,插入后子表元素的外键将被设置为0 –
这不处理事物的更新方面。 –
它是免费的吗?或者我需要为它付费吗?。这是一样的http://entityframework-extensions.net/#pro? –
创建临时表: 的SqlCommand(的String.Format(“SELECT TOP 0 * INTO {0} FROM {1} ...
将数据批量插入到它中 - 上面提到的实体框架扩展需要进行调整以支持临时表名,但其他方面是正确的 - 或者滚动一些代码并使用SqlBulkCopy。
构造MERGE语句。
如果你是我的一个属性列表,你可以使(2)和(3)通用。我可以在大约20秒内读取并合并150,000行。
[在实体框架中插入的最快方式]的可能重复(http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework) –
这里是非常好的答案。 [http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework][1] [1]:HTTP://计算器。 com/questions/5940225 /插入实体框架的最快方式 –