【问题标题】:TransactionScope and DataContextTransactionScope 和 DataContext
【发布时间】:2010-11-26 13:03:39
【问题描述】:

我知道这个问题以前一直在问,但我还没有找到真正有效的答案。

当我的单元测试尝试调用使用 Linq 查询数据库的 Web 服务时,出现了我的问题。

单元测试是这样设置的:

[TestInitialize]
public void SetUp()
{
    var scope = new TransactionScope(TransactionScopeOption.Required,TimeSpan.MaxValue);
    var database = new DatabaseDataContext();
}

[TestCleanup]
public void TearDown()
{
    scope.Dispose();
    database.Dispose();
}

[TestMethod]
public void GetCategoryList_Success()
{
    // create test data
    var result = service.GetItems();
}

service.GetItems 方法如下所示:

try
{
    using (DatabaseDataContext database = new DatabaseDataContext())
    {
        var items = (from i in database.Items
                    select i).ToList<Items>();
        return items;
    }
}
catch (Exception ex)
{
   // log error
   return null;
}

当 Linq 查询尝试执行时,抛出以下异常:

该操作对于事务的状态无效。

我相信这与嵌套事务有关,但我需要保持测试类中的事务处于打开状态,以便测试数据实际上不会保存到数据库中,并且一旦运行测试我就可以将其处理掉。

另外,我的主机位于共享实例上,因此我无法直接对服务器进行任何更改。

有没有办法让它按原样工作,或者在这种情况下是否有替代使用 TransactionScope 的方法?

【问题讨论】:

    标签: c# asp.net unit-testing transactions datacontext


    【解决方案1】:

    您正尝试在单个 TransactionScope 内创建到同一个数据库的两个连接 - 一个用于测试进程,另一个用于 Web 服务进程。这不起作用,因为在数据库中来自不同进程的事务显然不能嵌套。

    您应该在此处更改测试方法。阅读 Jan 的回答。

    作为一种解决方法,您可以让您的网络服务管理事务。一个方法,比如说,BeginGlobalTran 应该为 Web 服务创建一个全局事务(或 TransactionScope)对象(存储在属性中),它的所有其他方法都应该使用这个对象(因此,所有其他事务都嵌套在“全局”事务中),另一种方法说,RollbackGlobalTran 应该回滚这个“全局”事务。
    话虽如此,这是一种解决方法,它可能会导致一些意想不到的副作用(例如,方法中的错误会使“全局”事务无法提交,因此您必须重新启动它以避免进一步的错误)。

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多