C# SqlDataReader与数据库访问并发

C# SqlDataReader与数据库访问并发,c#,asp.net,.net,database,concurrency,C#,Asp.net,.net,Database,Concurrency,说明我的问题的最简单方法是使用以下C#代码: 那么在这种情况下,rdr中的数据会发生什么情况呢?我实际测试了这个。测试代码: using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["test"].ConnectionString)) { conn.Open(); using (SqlCommand comm = new SqlCommand("select * fr

说明我的问题的最简单方法是使用以下C#代码:


那么在这种情况下,
rdr
中的数据会发生什么情况呢?

我实际测试了这个。测试代码:

using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["test"].ConnectionString))
{
    conn.Open();
    using (SqlCommand comm = new SqlCommand("select * from test", conn))
    {
        using (var reader = comm.ExecuteReader())
        {
            int i = 0;
            while (reader.Read())
            {
                if ((string)reader[1] == "stop")
                {
                    throw new Exception("Stop was found");
                }
            }
        }
    }
}
为了测试,我用一些虚拟数据初始化了表(确保没有包含值为“stop”的行)。然后我在
inti=0的行上放置一个断点。当执行在断点处停止时,我在表中插入了一行“stop”值

结果是,根据表中初始行的数量,抛出/未抛出
异常。我没有试图确定行限制的确切位置。对于十行,没有抛出异常
,这意味着读者没有注意到从另一个进程添加的行。有一万行,异常被抛出

所以答案是:这要看情况而定。如果不将命令/读取器包装在
事务中
,则不能依赖这两种行为

强制性免责声明:这就是它在我的环境中的工作方式

编辑:

我在我的开发机器上使用本地Sql server进行了测试。它报告自己为:

Microsoft SQL Server 2008 R2(SP1)-10.50.2550.0(X64)

关于交易:

下面是我使用事务的代码:

using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["test"].ConnectionString))
{
    conn.Open();
    using (var trans = conn.BeginTransaction())
    using (SqlCommand comm = new SqlCommand("select * from test", conn, trans))
    {
        using (var reader = comm.ExecuteReader())
        {
            int i = 0;
            while (reader.Read())
            {
                i++;
                if ((string)reader[1] == "stop")
                {
                    throw new Exception("Stop was found");
                }
            }
        }
        trans.Commit();
    }
}
在这段代码中,我创建事务时没有显式指定隔离级别。这通常意味着将使用
System.Data.IsolationLevel.ReadCommitted
(我认为默认隔离级别可以在Sql Server设置的某个地方设置)。在这种情况下,读卡器的行为与以前相同。如果我将其更改为使用:

...
using (var trans = conn.BeginTransaction(System.Data.IsolationLevel.Serializable))
...

“停止”记录的插入被阻止,直到事务提交。这意味着,当读卡器处于活动状态时,Sql Server不允许对底层数据进行任何更改。

我假定您得到的是旧数据。结果在查询执行时返回,并存储在客户端的网络缓冲区中,直到您使用DataReader的Read方法请求它们为止。但这取决于隔离级别。看看这个答案:@TimSchmelter:好的。谢谢你的链接,尽管你自己的答案有点模棱两可。你说我会得到旧数据,但最后你说这取决于隔离级别。那是哪一个呢?这个“隔离级别”是什么?如果它是一个答案,我会编辑它并删除第一句;-)@ahmd0我只是做了一些测试,然后得到了旧数据——我运行
select*
@Aristos时得到的数据:谢谢。那么Tim提出的SQL Server隔离级别呢?感谢您做了这个测试。您在哪个版本的SQL Server上运行它?另外,您能否演示如何将其包装到
事务中?
...
using (var trans = conn.BeginTransaction(System.Data.IsolationLevel.Serializable))
...