如果自定义工作单元中可能有多个DbContexts,EF5会管理所有交易要求,还是下面的代码仍然有效/需要?如果没有,代码可以减少多少并仍然提供相同的功能?
public void SaveAllChanges()
{
var transactions = new List<DbTransaction>();
foreach (var context in this.contexts
.Where(context => context != null)
.Select(dbcontext => ((IObjectContextAdapter)dbcontext).ObjectContext))
{
context.Connection.Open();
var databaseTransaction = context.Connection.BeginTransaction();
transactions.Add(databaseTransaction);
try
{
context.SaveChanges();
}
catch
{
foreach (var transaction in transactions)
{
try
{
transaction.Rollback();
}
finally
{
databaseTransaction.Dispose();
}
}
transactions.Clear();
throw;
}
}
try
{
foreach (var transaction in transactions)
{
transaction.Commit();
}
}
finally
{
foreach (var transaction in transactions)
{
transaction.Dispose();
}
transactions.Clear();
foreach (var context in this.contexts
.Select(dbcontext => ((IObjectContextAdapter)dbcontext).ObjectContext)
.Where(context => context.Connection.State != ConnectionState.Closed))
{
context.Connection.Close();
}
}
}
假设SQL Server 2008及更高版本。
答案 0 :(得分:0)
在使用多个上下文但您的代码错误时,您必须处理自己的事务。如果您的任何事务在提交期间失败,您可以提交部分事务并回滚部分事务。
唯一有效的方法是手动使用TransactionScope
和manage connections,或者使用分布式交易:
var objectContexts = this.contexts
.Where(context => context != null)
.Select(dbcontext => ((IObjectContextAdapter)dbcontext).ObjectContext))
.ToArray();
var transactionOptions = new TransactionOptions {
IsolationLevel = IsolationLevel.ReadCommitted
};
using (var scope = new TransactionScope(TransactionScopeOption.Required,
transactionOptions)) {
Array.ForEach(objectContext,
o => o.SaveChanges(SaveOptions.DetectChangesBeforeSave));
scope.Complete();
}
Array.ForEach(objectContext, o => o.AcceptAllChanges());
描述 Here为什么AcceptAllChanges很重要。