Linq to SQL事务范围

4
我有以下情景:
 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },EnterpriseServicesInteropOption.Automatic))
 {
  using (DataContext db = new DataContext())
  {
    db.Connection.Open();
    db.Transaction = db.Connection.BeginTransaction();
    try
    {
      bool outcome = InvokeInTransaction<string, object>(inputDict, out outputDict);
      db.Transaction.Commit();
    }
    catch (Exception ex)
    {
      response.Outcome = BusinessEntityResponse.SystemError;
      db.Transaction.Rollback();
    }
  }
}

在InvokeInTransaction调用中,会对LTS存储库进行多个调用以执行各种数据更改。问题在于,在存储库内部还有另一个


using (var db = new DataContext())

这里面是持久化代码。检查存储库中的上下文会显示事务为 null,我怀疑“内部”上下文没有知道环境事务的存在。这可行吗?我知道 EF 在后台管理这个,但约束是不能更改存储库代码。需要帮助吗?

1个回答

5

我们使用 LinqToSql 和 TransactionScope 来进行多个数据库事务。如果您要尝试这样做,应该真正控制连接/上下文/事务的生命周期。

  • 我们通过规则来控制 DataContext 实例:如果您需要一个新实例,可以在 using 语句中实例化。
  • 我们通过规则来控制连接的生命周期:如果您打开它,则必须关闭它(但通常让 DataContext 实例管理它)。
  • 我们通过规则来控制事务的生命周期:让 DataContext 在 SubmitChanges 中处理其操作,让 TransactionScope 在其 using 块内处理其操作。

以下是示例代码:

using (OuterDataContext outerDataContext = GetOuterDataContext())
{
  using (InnerDataContext innerDataContext = GetInnerDataContext())
  {
    try
    {
      OuterRepository outerRepository = new OuterRepository();
        // may read records into memory for updating/deleting.
      outerRepository.WorkWithOuterRecords(outerRecords, outerDataContext);

      InnerRepository innerRepository = new InnerRepository();
        // may read records into memory for updating/deleting.
      innerRepository.WorkWithInnerRecords(innerRecords, innerDataContext);

      using (TransactionScope scope = new TransactionScope())
      {
          //starts a local tranaction in outerDB, held open by scope
        outerDataContext.SubmitChanges();  
          //promotes the transaction to distributed, still held open by scope
        innerDataContext.SubmitChanges();
          // and done
        scope.Complete();
      }
    }
    catch (Exception ex)
    {
       LoggerClient.Log(ex);
       response.Message = "It didn't save anything.";
    }
  }
}

谢谢David,这个模式看起来确实是一个很好的实现,我喜欢使用WorkWith*Records来维护上下文范围,但我无法解决我的存储库类的旧代码实现问题(需要对调用这些类的代码进行大量重构)。因此才会有这个最初的问题。不过这是一个不错的模式。 - OldBoy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接