是否有必要在Entity Framework 5中管理交易? (多个上下文)

时间:2012-09-16 23:59:17

标签: entity-framework transactions

如果自定义工作单元中可能有多个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及更高版本。

1 个答案:

答案 0 :(得分:0)

在使用多个上下文但您的代码错误时,您必须处理自己的事务。如果您的任何事务在提交期间失败,您可以提交部分事务并回滚部分事务。

唯一有效的方法是手动使用TransactionScopemanage 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很重要。