.Net / SQL Server竞争条件

时间:2015-10-29 09:35:25

标签: c# sql-server database race-condition

我的集成测试如下所示:

[TestMethod]
    public async Task TestMethod1()
    {
        Guid guid = Guid.NewGuid();

        using (HttpClient client = new HttpClient())
            await client.GetAsync(String.Format(_uri, guid.ToString()));

        Guid retrieved = GetLastGuid();
        Assert.AreEqual(guid, retrieved);
    }

client.GetAsync正在呼叫一个简单的Web服务,它将Guid保存在数据库表中。 GetLastGuid对表执行以下查询:

select top 1 * from dbo.Messages order by MessageId desc

其中message id是消息表上的标识列。

将试图测试数据库交互的智慧放在一边,我看到以下行为,从纯粹的技术角度来看,我很想知道发生了什么。

我期待发生什么

该服务已被调用,Guid将保存到数据库中。查找数据库表中的最新行将返回最后一个条目。我的理解(以及我怀疑我不正确的地方)是在SQL服务器上执行存储过程是一个同步过程,即它在提交事务之前不会返回。

实际发生的事情

将几次调用链接到我的测试方法会导致其中一些失败。看起来他们正在为之前的电话检索Guid。

我认为可能是原因

我怀疑我假设存储过程调用是同步的,并且我的失败测试实际上是在上一次事务提交之前尝试读取最新值。唯一让我怀疑的是,将GetLastGuid查询设置为未提交读取仍会导致同样的问题。

所有测试方法都按顺序运行,没有其他内容写入此数据库表。明智地使用Thread.Sleep /在调试模式下运行可以解决问题,这是竞争条件的所有经典迹象。

1 个答案:

答案 0 :(得分:1)

select top 1并不保证能为您提供正确的guid。您应该指定从dbo.Messages中选择*,其中guid = @guid或者从http客户端调用返回messageid(?)并使用它来获取数据并比较guid。虽然如果没有返回数据应该是第一个要检查的断言。