我有一个标识列为FOO
的表ID
。在事务中,我使用id
1锁定行。
如果我在另一个事务中在SQL Server Management Studio中尝试这一行SQL:
select * from FOO with (updlock, rowlock, nowait) where ID = 1
...我收到此错误:
Msg 1222, Level 16, State 51, Line 1
Lock request time out period exceeded.
哪个好,因为那就是所谓的发生的事情。
我有这个测试代码(省略错误处理):
internal class Constants
{
public const string CONNECT = @"Data Source=.\TEST;Initial Catalog=TEST;User ID=YOURNAME;Password=" + "\"\"" + @";Integrated Security=SSPI;";
public const string COMMAND = "select * from FOO with (updlock, rowlock, nowait) where ID = 1";
}
internal class Locker
{
private SqlConnection _connect;
private SqlTransaction _transact;
public void Lock()
{
_connect = new SqlConnection(Constants.CONNECT);
_connect.Open();
_transact = _connect.BeginTransaction();
using (var cmd = new SqlCommand(Constants.COMMAND, _connect, _transact))
{
using (var reader = cmd.ExecuteReader(CommandBehavior.SingleResult))
{
if (reader.HasRows)
reader.Read();
}
}
}
public void Unlock()
{
_transact.Rollback();
_transact.Dispose();
_connect.Close();
_connect.Dispose();
}
}
internal class Tester
{
public int Test()
{
int count;
using (var connect = new SqlConnection(Constants.CONNECT))
{
connect.Open();
using (var transact = connect.BeginTransaction())
{
using (var cmd = new SqlCommand(Constants.COMMAND, connect, transact))
{
try
{
using (var reader = cmd.ExecuteReader(CommandBehavior.SingleResult))
{
count = 0;
if (reader.HasRows)
while (reader.Read())
count++;
}
}
catch (SqlException)
{
count = -1;
}
}
transact.Rollback();
}
connect.Close();
}
return count;
}
}
如果我然后创建Locker
和Tester
并让测试人员在锁定器锁定时尝试选择该行,tester.Test()
会返回 0
命令不应该抛出锁定超时异常,该方法会捕获&通过返回-1表示?如果没有,我如何区分“没有这样的行存在”和“该行存在但其他人将其锁定”之间的区别?为什么这在SSMS中工作正常但在C#中没有?
它的行为类似于提供READPAST
table hint,但我们可以在代码中清楚地看到它不是。是否有任何方式可以在.NET库代码中以某种方式设置提示的行为?
注意:我已经尝试过使用储物柜和放大器的每种隔离级别组合。测试人员以及超时期限,而不是使用NOWAIT
。