我使用这个技巧进行集成测试,以确保每个测试都在事务中运行,并且该事务会回滚:
我定义了以下基类,我的所有集成测试类都可以继承它。
public abstract class IntegrationTestBase
{
private TransactionScope scope;
[TestInitialize]
public void TestInitialize()
{
scope = new TransactionScope();
}
[TestCleanup]
public void TestCleanup()
{
scope.Dispose();
}
}
它可以工作,但不适用于以下代码:
[TestMethod]
public void SaveTwoDocumentsSimultaneously_WorkSuccessfully()
{
//Assign
var doc1 = new Document() { Number = "Test-1" };
var doc2 = new Document() { Number = "Test-2" };
//Action
Parallel.Invoke(() => SaveNewDocument(doc1), () => SaveNewDocument(doc2));
//Assert
Assert.IsTrue(true);
}
void SaveNewDocument(Document doc)
{
using (var ctx = new MyDbContext())
{
ctx.Documents.Add(doc);
ctx.SaveChanges();
}
}
测试通过后,数据库中有一条编号为Test-2的记录,换句话说,事务并没有按照我的预期回滚(我预计没有编号为Test-1的记录并且数据库中的Test-2)。
问题出在哪里以及如何解决?
您根本无法通过与数据库的一个连接来使用并发性。单个连接同步工作,如果您尝试使用一个连接并行进行查询,这将导致不可预测的行为。相反,如果您想并行查询数据库,请创建不同的连接并同时使用它们。 底线:一个连接一次允许一个查询。