我实际上对此进行了测试。测试代码:
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”的行)。然后我在行上放了一个断点int i = 0;
。当执行在断点处停止时,我在表中插入了一行带有“停止”值的行。
结果是,根据表中初始行的数量,Exception
抛出/未抛出。我没有试图确定行限制的确切位置。对于十行,Exception
没有抛出,这意味着读者没有注意到从另一个进程添加的行。一万行,抛出异常。
所以答案是:视情况而定。如果不将命令/阅读器包装在 aTransaction
中,则不能依赖任何一种行为。
强制性免责声明:这就是它在我的环境中的工作方式......
编辑:
我在我的开发机器上使用本地 Sql 服务器进行了测试。它报告自己为:
微软 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 不允许对底层数据进行任何更改。