简体   繁体   中英

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

In order to prevent long read operations from blocking short, frequent write operations in my existing mixed OLTP/reporting web application backed by SQL Server 2016, I want to use Snapshot Isolation on a few long-running queries. The queries have already been well indexed and just take a long time to run due to large amounts of data, and while I may use RCSI later, I would like to start by using the less invasive Snapshot Isolation.

My question is: how do I enable Snapshot Isolation on my SELECT queries in C#? It seems I would have to wrap my select queries in a transaction, which just feels totally wrong.

            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);
                            }
                        }
                    }
                }
            }

From http://www.levibotelho.com/development/plugging-isolation-leaks-in-sql-server/ I can see that in SQL Server 2014 and later the isolation level will be reset when the connection is returned to the pool, so that's good.

But can it be right to wrap a stored proc that does only SELECT in an ADO.NET transaction? Is there not some better way than this to implement Snapshot Isolation in C#?

No, you need to set the isolation level in the BeginTransaction methid:

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.

Otherwise, the default Read Committed mode is used and the READ will be blocked by the transactions modifying the table (possibly).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM