我意识到这个问题之前一直在问,但我还没有找到真正有用的答案。
当我的单元测试试图调用使用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?
答案 0 :(得分:0)
您正尝试在单个TransactionScope中创建与同一数据库的两个连接 - 一个用于测试过程,另一个用于Web服务过程。这不起作用,因为在数据库中来自不同进程的tranas明显无法嵌套。
您应该在此处更改您的测试方法。阅读Jan的回答。
作为解决方法,您可以让您的Web服务管理交易。一个方法,比如,BeginGlobalTran
应该为Web服务创建一个全局Transaction(或TransactionScope)对象(存储在property中),所有其他方法都应该使用这个对象(所以,所有其他事务都嵌套在'global “交易”,另一种方法是,RollbackGlobalTran
应该回滚这个“全球”交易
话虽如此,这是一种解决方法,它可能会导致一些意想不到的副作用(例如,方法中的错误将使'全局'事务无法承受,因此您必须重新启动它以避免进一步的错误。)