sql-server-2008 – TransactionScope和隔离级别

我们有一个问题要使用TransactionScope. TransactionScope让我们非常好的灵活性在我们的数据访问层使用事务.这样我们可以使用隐式或者显式的交易.有一些性能再次提升ADO.NET的交易,但在这个时候这并不是真的问题.但是我们有锁定的问题.在下面的示例代码中,虽然隔离级别设置为ReadCommitted,但是不可能在表testTable上从其他客户端进行Select SQL语句,直到主事务(在Main方法中)将被提交,因为整个表上都有锁定.我们还尝试在所有方法中使用一个连接,但是同样的行为.我们的DBMS是SQL Server 2008.有没有什么我们不明白?

问候
安东·卡尔奇克

请参阅此示例代码:

class Program
{
    public class DAL
    {
        private const string _connectionString = @"Data Source=localhost\fsdf;Initial Catalog=fasdfsa;Integrated Security=SSPI;";

        private const string inserttStr = @"INSERT INTO dbo.testTable (test) VALUES(@test);";

        /// <summary>
        /// Execute command on DBMS.
        /// </summary>
        /// <param name="command">Command to execute.</param>
        private void ExecuteNonQuery(IDbCommand command)
        {
            if (command == null)
                throw new ArgumentNullException("Parameter 'command' can't be null!");

            using (IDbConnection connection = new SqlConnection(_connectionString))
            {
                command.Connection = connection;
                connection.Open();
                command.ExecuteNonQuery();
            }
        }

        public void FirstMethod()
        {
            IDbCommand command = new SqlCommand(inserttStr);
            command.Parameters.Add(new SqlParameter("@test", "Hello1"));

            using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required))
            {
                ExecuteNonQuery(command);
                sc.Complete();
            }
        }

        public void SecondMethod()
        {
            IDbCommand command = new SqlCommand(inserttStr);
            command.Parameters.Add(new SqlParameter("@test", "Hello2"));

            using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required))
            {
                ExecuteNonQuery(command);
                sc.Complete();
            }
        }
    }

    static void Main(string[] args)
    {

        DAL dal = new DAL();
        TransactionOptions tso = new TransactionOptions();
        tso.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

        using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required,tso))
        {
            dal.FirstMethod();
            dal.SecondMethod();
            sc.Complete();
        }
    }
}
最佳答案
我不认为您的问题与.NET TransactionScope概念无关.相反,听起来您正在描述SQL Server事务的预期行为.此外,更改隔离级别只会影响“数据读取”而不是“数据写入”.从SQL Server BOL:

“Choosing a transaction isolation level does not affect the locks acquired to protect data modifications. A transaction always gets an exclusive lock on any data it modifies, and holds that lock until the transaction completes, regardless of the isolation level set for that transaction. For read operations, transaction isolation levels primarily define the level of protection from the effects of modifications made by other transactions.”

这意味着您可以通过更改发出SELECT语句的客户端的隔离级别来防止阻止行为. READ COMMITED隔离级别(默认值)不会阻止阻塞.为了防止阻塞客户端,您将使用READ UNCOMMITTED隔离级别,但您必须考虑可能检索已由开放事务更新/插入的记录的可能性(即如果事务回滚,它们可能会消失).

转载注明原文:sql-server-2008 – TransactionScope和隔离级别 - 代码日志