【发布时间】:2011-10-07 14:22:20
【问题描述】:
我正在构建一个批处理系统。 Units 的批次数量为 20-1000 个。每个Unit 本质上是一个模型层次结构(一个主模型和许多子模型)。我的任务涉及将每个模型层次结构作为单个事务保存到数据库中(每个层次结构都提交或回滚)。不幸的是,EF 无法处理模型层次结构的两个部分,因为它们可能包含数千条记录。
我为解决此问题所做的工作是设置 SqlBulkCopy 来处理这两个潜在的高计数模型,并让 EF 处理其余的插入(以及引用完整性)。
批处理循环:
foreach (var unitDetails in BatchUnits)
{
var unitOfWork = new Unit(unitDetails);
Task.Factory.StartNew(() =>
{
unitOfWork.ProcessX(); // data preparation
unitOfWork.ProcessY(); // data preparation
unitOfWork.PersistCase();
});
}
单位:
class Unit
{
public PersistCase()
{
using (var dbContext = new CustomDbContext())
{
// Need an explicit transaction so that
// EF + SqlBulkCopy act as a single block
using (var scope = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions() {
IsolationLevel = System.Transaction.IsolationLevel.ReadCommitted
}))
{
// Let EF Insert most of the records
// Note Insert is all it is doing, no update or delete
dbContext.Units.Add(thisUnit);
dbContext.SaveChanges(); // deadlocks, DbConcurrencyExceptions here
// Copy Auto Inc Generated Id (set by EF) to DataTables
// for referential integrity of SqlBulkCopy inserts
CopyGeneratedId(thisUnit.AutoIncrementedId, dataTables);
// Execute SqlBulkCopy for potentially numerous model #1
SqlBulkCopy bulkCopy1 = new SqlBulkCopy(...);
...
bulkCopy1.WriteToServer(dataTables["#1"]);
// Execute SqlBulkCopy for potentially number model #2
SqlBulkCopy bulkCopy2 = new SqlBulkCopy(...);
...
bulkCopy2.WriteToServer(dataTables["#2"]);
// Commit transaction
scope.Complete();
}
}
}
}
现在我基本上被困在一块石头和一个坚硬的地方之间。如果我将IsolationLevel 设置为ReadCommitted,我会在不同Tasks 中的EF INSERT 语句之间出现死锁。
如果我将IsolationLevel 设置为ReadUncommitted(我认为这很好,因为我没有做任何SELECTs)我得到DbConcurrencyExceptions。
我一直无法找到有关 DbConcurrencyExceptions 和 Entity Framework 的任何有用信息,但我猜测 ReadUncommitted 本质上是导致 EF 收到无效的“插入的行”信息。
更新
以下是有关在执行 INSERTS 时实际导致我的死锁问题的一些背景信息:
显然,几年前当 Linq To SQL 出现时,同样的问题也出现了,微软通过更改选择 scope_identity() 的方式来修复它。不知道为什么当实体框架出现同样的问题时,他们的立场变成了 SQL Server 问题。
【问题讨论】:
-
竞争还是完成?
标签: c# .net entity-framework transactions sqlbulkcopy