使用快照隔离snapshot isolation实例(二)

示例

以下示例演示修改数据时的快照隔离行为。该代码执行下列操作:

  • 连接到 AdventureWorks 示例数据库并启用 SNAPSHOT 隔离。

  • 创建一个名为 TestSnapshotUpdate 的表并插入三行示例数据。

  • 使用 SNAPSHOT 隔离开始但是不完成 sqlTransaction1。在事务中选择三行数据。

  • 创建第二个与 AdventureWorks 的 SqlConnection,并使用 READ COMMITTED 隔离级别创建第二个事务,更新在 sqlTransaction1 中选择的其中一行的值。

  • 提交 sqlTransaction2。

  • 返回 sqlTransaction1 并尝试更新 sqlTransaction2 已提交的相同的行。将引发 3960 错误,sqlTransaction1 将自动回滚。控制台窗口中将显示 SqlException.Number 和 SqlException.Message。

  • 执行清理代码以禁用 AdventureWorks 中的快照隔离并删除 TestSnapshotUpdate 表。

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
namespace snapshot2
{
    class Program
    {
        static void Main(string[] args)
        {
            string connectionString = @"Data Source=XUWEI/SQLEXPRESS;Initial Catalog=AdventureWorks;User ID=sa;Password=sa12345";
            using (SqlConnection connection1 = new SqlConnection(connectionString))
            {
                connection1.Open();
                SqlCommand command1 = connection1.CreateCommand();
                // Enable Snapshot isolation in AdventureWorks,设置数据库使其支持快照隔离(Snapshot isolation)技术。
                command1.CommandText =
                    "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION ON";
                try
                {
                    command1.ExecuteNonQuery();
                    Console.WriteLine(
                        "Snapshot Isolation turned on in AdventureWorks.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("ALLOW_SNAPSHOT_ISOLATION ON failed: {0}", ex.Message);
                }
                // Create a table ,创建表格。
                command1.CommandText =
                    "IF EXISTS "
                    + "(SELECT * FROM sys.tables "
                    + "WHERE name=N'TestSnapshotUpdate')"
                    + " DROP TABLE TestSnapshotUpdate";
                command1.ExecuteNonQuery();
                command1.CommandText =
                    "CREATE TABLE TestSnapshotUpdate "
                    + "(ID int primary key, CharCol nvarchar(100));";
                try
                {
                    command1.ExecuteNonQuery();
                    Console.WriteLine("TestSnapshotUpdate table created.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("CREATE TABLE failed: {0}", ex.Message);
                }
                // Insert some data,在表中创建数据。
                command1.CommandText =
                    "INSERT INTO TestSnapshotUpdate VALUES (1,N'abcdefg');"
                    + "INSERT INTO TestSnapshotUpdate VALUES (2,N'hijklmn');"
                    + "INSERT INTO TestSnapshotUpdate VALUES (3,N'opqrstuv');";
                try
                {
                    command1.ExecuteNonQuery();
                    Console.WriteLine("Data inserted TestSnapshotUpdate table.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                // Begin, but do not complete, a transaction 
                // using the Snapshot isolation level.
                /*开始但不完成一个在快照隔离级别上的事务,
                 */
                SqlTransaction transaction1 = null;
                try
                {
                    transaction1 = connection1.BeginTransaction(IsolationLevel.Snapshot);
                    command1.CommandText =
                        "SELECT * FROM TestSnapshotUpdate WHERE ID BETWEEN 1 AND 3";
                    command1.Transaction = transaction1;
                    command1.ExecuteNonQuery();
                    Console.WriteLine("Snapshot transaction1 started.");
                    // Open a second Connection/Transaction to update data
                    // using ReadCommitted. This transaction should succeed.
                    /*打开第二个数据库连接,并创建一个在ReadCommitted上更新数据的事务。
                     * 这个事务能够成功。 
                     */
                    using (SqlConnection connection2 = new SqlConnection(connectionString))
                    {
                        connection2.Open();
                        SqlCommand command2 = connection2.CreateCommand();
                        command2.CommandText = "UPDATE TestSnapshotUpdate SET CharCol="
                            + "N'New value from Connection2' WHERE ID=1";
                        SqlTransaction transaction2 =
                            connection2.BeginTransaction(IsolationLevel.ReadCommitted);
                        command2.Transaction = transaction2;
                        try
                        {
                            command2.ExecuteNonQuery();
                            transaction2.Commit();//提交事务2
                            Console.WriteLine(
                                "transaction2 has modified data and committed.");
                        }
                        catch (SqlException ex)
                        {
                            Console.WriteLine(ex.Message);
                            transaction2.Rollback();
                        }
                        finally
                        {
                            transaction2.Dispose();
                        }
                    }
                    // Now try to update a row in Connection1/Transaction1.
                    // This transaction should fail because Transaction2
                    // succeeded in modifying the data.
                    /*试图更新连接1和事务1中的一行数据。这个事务执行失败,
                     * 这是因为在事务2中已经成功修改了数据。
                     * 事务1将自动回滚。
                     */
                    command1.CommandText =
                        "UPDATE TestSnapshotUpdate SET CharCol="
                        + "N'New value from Connection1' WHERE ID=1";
                    command1.Transaction = transaction1;
                    command1.ExecuteNonQuery();
                    transaction1.Commit();
                    Console.WriteLine("You should never see this.");//正常执行情况下应该不会再控制台中输出此句。
                }
                catch (SqlException ex)
                {
                    Console.WriteLine("Expected failure for transaction1:");
                    Console.WriteLine("  {0}: {1}", ex.Number, ex.Message);
                }
                finally
                {
                    transaction1.Dispose();
                }
            }
            // CLEANUP:清理程序
            // Turn off Snapshot isolation and delete the table
            using (SqlConnection connection3 = new SqlConnection(connectionString))
            {
                connection3.Open();
                SqlCommand command3 = connection3.CreateCommand();
                command3.CommandText =
                    "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION OFF";
                try
                {
                    command3.ExecuteNonQuery();
                    Console.WriteLine(
                        "CLEANUP: Snapshot isolation turned off in AdventureWorks.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("CLEANUP FAILED: {0}", ex.Message);
                }
                command3.CommandText = "DROP TABLE TestSnapshotUpdate";
                try
                {
                    command3.ExecuteNonQuery();
                    Console.WriteLine("CLEANUP: TestSnapshotUpdate table deleted.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("CLEANUP FAILED: {0}", ex.Message);
                }
            }
        }
    }
}
作者:xwdreamer
欢迎任何形式的转载,但请务必注明出处。
分享到:
原文地址:https://www.cnblogs.com/xwdreamer/p/2297079.html