在 C#/ADO.NET 中为 SELECT 查询实施 SQL Server 2016 快照隔离

Implement SQL Server 2016 Snapshot Isolation in C#/ADO.NET for SELECT queries

为了防止长读操作阻塞我现有的由 SQL Server 2016 支持的混合 OLTP/reporting Web 应用程序中频繁的短写操作,我想在一些长的上使用快照隔离-运行宁查询。这些查询已经很好地建立了索引,并且由于大量数据需要很长时间 运行,虽然我稍后可能会使用 RCSI,但我想从使用侵入性较小的快照隔离开始。

我的问题是:如何在 C# 中对我的 SELECT 查询启用快照隔离?看来我必须将我的 select 查询包含在事务中,这感觉完全错误。

            List<Cat> cats = new List<Cat>();
            TransactionOptions transactionOption = new TransactionOptions
            {
                IsolationLevel = IsolationLevel.Snapshot
            };
            using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOption))
            {
                using (SqlConnection sqlConnection = new SqlConnection(databaseConnectionString))
                {
                    using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
                    {
                        sqlCommand.CommandText = "proc_Select_A_Billion_Cats";
                        sqlCommand.CommandType = CommandType.StoredProcedure;

                        sqlConnection.Open();

                        using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
                        {
                            while (sqlDataReader.Read())
                            {
                                // SOME CODE HERE can read the Cat object in from data reader

                                // Add this cat to the collection
                                cats.Add(cat);
                            }
                        }
                    }
                }
            }

http://www.levibotelho.com/development/plugging-isolation-leaks-in-sql-server/ 我可以看到,在 SQL Server 2014 及更高版本中,当连接返回池时,隔离级别将被重置,这很好。

但是将只执行 SELECT 的存储过程包装在 ADO.NET 事务中是否正确?有没有比这更好的方法来在 C# 中实现快照隔离?

不,您需要在 BeginTransaction 方法中 set the isolation level

If a database has been enabled for snapshot isolation but is not configured for READ_COMMITTED_SNAPSHOT ON, you must initiate a SqlTransaction using the IsolationLevel.Snapshot enumeration value when calling the BeginTransaction method.

否则,使用默认的Read Committed模式,READ将被修改table的事务阻塞(可能)。