如何在未启动事务的SqlCommand/SqlConnection上设置隔离级别

29

以下方法应该在打开的连接上执行脏读取,没有事务。我在哪里设置 IsolationLevel?

public string DoDirtyRead(string storedProcName, SqlConnection connection)
{
    using (SqlCommand command = new SqlCommand(storedProcName, connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        // HOW TO SET IsolationLevel to READ_UNCOMMITTED here?
        command.ExecuteNonQuery();
    }
}
5个回答

26
如果您不想进行事务处理,可以在打开连接时仅设置一次,它将一直保持在该设置状态,直至您更改它。因此,请执行以下操作:
connection.BeginTransaction(IsolationLevel.ReadUncommitted).Commit();

对于你的特定情况可能不是最好的选择,因为你打开连接、使用它,然后丢弃它,但我想为那些拥有更长寿命连接的人提供这个答案。


1
BeginTransaction返回一个IDisposable的DbTransaction。如果你丢弃了引用,在哪里调用Dispose呢? - ta.speot.is
6
如果您想避免使用一次性返回对象,另一个选项是在打开连接后执行非查询的 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;。然后该连接将保持这种状态,直到它被关闭或以其他方式被修改。 - DarrenMB
9
注意连接池... 当你使用相同的连接字符串创建下一个“新”的连接时,它会返回你之前使用过的旧连接,并且会保持之前设置的隔离级别不变。 - foxontherock

12

关于BeginTransaction方法:(MSDN链接)

如果您仅想在存储过程中使用表级提示,请使用WITH(NOLOCK),但请自行承担风险。


(所以您需要在事务中设置隔离级别,或者只需在存储过程中使用提示。) - Bob Palmer
我根本不想使用事务。 - kateroh
1
好的,必须执行事务并传递 read_uncommitted。谢谢! - kateroh

9

假设您已经有一个现有的连接(可能还有一个现有的事务),我建议使用TransactionScope来控制子级的隔离级别。这将执行脏读取行数(我相信):

using (var command = connection.CreateCommand())
using(new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions{IsolationLevel = IsolationLevel.ReadUncommitted}))
{
    command.CommandText = string.Format("select count(*) from {0}", tableName);
    return (int)command.ExecuteScalar();
}

在.NET5+中,我如何设置隔离级别(IsolationLevel)? - Patrick Szalapski

7

在您的存储过程中,对于Transact-SQL使用:

SET TRANSACTION ISOLATION LEVEL read uncommitted    -- 0
SET TRANSACTION ISOLATION LEVEL read committed     -- 1
SET TRANSACTION ISOLATION LEVEL repeatable read    -- 2
SET TRANSACTION ISOLATION LEVEL read serializable  -- 3

此外,考虑为您的表设置DATAROWS锁定方案。 - ArBR
谢谢你的回答。这并没有帮助,因为它会让存储过程一直进行脏读取。相反,我想在我的代码中使用事务来控制它,或者如果可能的话,不使用事务,这样存储过程就可以以任何隔离级别被调用。 - kateroh

0

在你的存储过程中添加另一个参数,以指示你希望存储过程运行的隔离级别。

如果 @isolevel = 0 SET TRANSACTION ISOLATION LEVEL read uncommitted; 否则

我认为 "uncommitted" 需要两个 "t"。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接