TransactionScope和DataContext

时间:2010-11-26 13:03:39

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

我意识到这个问题之前一直在问,但我还没有找到真正有用的答案。

当我的单元测试试图调用使用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查询尝试执行时,抛出以下异常:

  

该操作对交易状态无效。

我认为这与嵌套事务有关,但是我需要保持测试类中的事务处于打开状态,以便测试数据实际上不会保存到数据库中,并且我可以在测试运行后处理它。 / p>

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

有没有办法让它按原样运行,或者在这种情况下是否可以使用TransactionScope?

1 个答案:

答案 0 :(得分:0)

您正尝试在单个TransactionScope中创建与同一数据库的两个连接 - 一个用于测试过程,另一个用于Web服务过程。这不起作用,因为在数据库中来自不同进程的tranas明显无法嵌套。

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

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