IsolationLevel IsolationLevel IsolationLevel IsolationLevel Enum

Définition

Spécifie le comportement de verrouillage des transactions pour la connexion.Specifies the transaction locking behavior for the connection.

Cette énumération a un attribut FlagsAttribute qui permet une combinaison au niveau du bit de ses valeurs membres.

public enum class IsolationLevel
[System.Flags]
public enum IsolationLevel
type IsolationLevel = 
Public Enum IsolationLevel
Héritage
IsolationLevelIsolationLevelIsolationLevelIsolationLevel
Attributs

Champs

Chaos Chaos Chaos Chaos 16

Les modifications en attente, provenant des transactions les plus isolées, ne peuvent pas être remplacées.The pending changes from more highly isolated transactions cannot be overwritten.

ReadCommitted ReadCommitted ReadCommitted ReadCommitted 4096

Les verrous partagés sont conservés pendant la lecture des données afin d'éviter tout défaut de lecture, mais les données peuvent être modifiées avant la fin de la transaction, entraînant ainsi des données fantômes ou des lectures qui ne peuvent pas être répétées.Shared locks are held while the data is being read to avoid dirty reads, but the data can be changed before the end of the transaction, resulting in non-repeatable reads or phantom data.

ReadUncommitted ReadUncommitted ReadUncommitted ReadUncommitted 256

Un défaut de lecture est possible, ce qui signifie qu'aucun verrou partagé n'est émis et qu'aucun verrou exclusif n'est respecté.A dirty read is possible, meaning that no shared locks are issued and no exclusive locks are honored.

RepeatableRead RepeatableRead RepeatableRead RepeatableRead 65536

Des verrous sont placés sur toutes les données utilisées dans une requête afin d’empêcher d’autres utilisateurs de mettre à jour les données.Locks are placed on all data that is used in a query, preventing other users from updating the data. Empêche les lectures qui ne peuvent pas être répétées, mais des lignes fantômes peuvent toujours exister.Prevents non-repeatable reads but phantom rows are still possible.

Serializable Serializable Serializable Serializable 1048576

Un verrou de plage est placé sur DataSet afin d'empêcher les autres utilisateurs de mettre à jour ou de modifier les lignes du groupe de données avant la fin de la transaction.A range lock is placed on the DataSet, preventing other users from updating or inserting rows into the dataset until the transaction is complete.

Snapshot Snapshot Snapshot Snapshot 16777216

Réduit le blocage en stockant une version des données qu'une application pourra lire pendant qu'une autre les modifiera.Reduces blocking by storing a version of data that one application can read while another is modifying the same data. Indique qu'il n'est pas possible de voir les modifications apportées dans une transaction à partir d'une autre transaction, même si vous réexécutez la requête.Indicates that from one transaction you cannot see changes made in other transactions, even if you requery.

Unspecified Unspecified Unspecified Unspecified -1

Un niveau d'isolement différent de celui spécifié est utilisé actuellement, mais il est impossible de le déterminer.A different isolation level than the one specified is being used, but the level cannot be determined.

Exemples

Cette application montre comment utiliser IsolationLevel dans DbTransaction.This application demonstrates how to use IsolationLevel in DbTransaction. L’exemple va vous montrer parmi les comportements suivants sont autorisés dans les différents niveaux d’isolation :The sample will demonstrate which of the following behaviors are allowed in the different isolation levels:

  • Lectures erronées.Dirty reads.

  • Lectures non reproductibles.Non-repeatable reads.

  • Fantômes.Phantoms.

Cette application s’exécute dans les niveaux d’isolation suivants :This application will execute in the following isolation levels:

  • ReadUncommittedReadUncommitted

  • ReadCommittedReadCommitted

  • RepeatableReadRepeatableRead

  • SérialisableSerializable

  • InstantanéSnapshot

La classe PhantomReadThreads montre si la transaction spécifique permet le comportement en lecture fantôme.The PhantomReadThreads class demonstrates if the specific transaction allows the Phantom Read behavior. Si la transaction autorise le comportement, les threads fonctionnera dans l’ordre suivant :If the transaction allows the behavior, the threads will operate in the following order:

  • Dans le premier thread, sélectionnez le products(All).In first thread, select the products(All).

  • Dans le deuxième thread, insérez un nouveau produit.In the second thread, insert a new product.

  • Valider la transaction dans le deuxième thread.Commit the transaction in second thread.

  • Sélectionnez les produits à nouveau.Select the products again.

  • Valider la transaction dans le premier thread.Commit the transaction in first thread.

Si la transaction autorise le comportement, les deux opérations Select obtiendra des résultats différents.If the transaction allows the behavior, the two Select operations will get the different results.

La classe NonrepeatableReadThreads montre si la transaction spécifique autorise le comportement de lecture non renouvelable.The NonrepeatableReadThreads class demonstrates if the specific transaction allows the Nonrepeatable Read behavior. Si la transaction autorise le comportement, les threads fonctionnera dans l’ordre suivant :If the transaction allows the behavior, the threads will operate in the following order:

  • Dans le premier thread, sélectionnez le product(ProductId=1).In first thread, select the product(ProductId=1).

  • Dans le deuxième thread, mettre à jour la quantité value(ProductId=1).In the second thread, update the Quantity value(ProductId=1).

  • Valider la transaction dans le deuxième thread.Commit the transaction in second thread.

  • Sélectionnez le produit à nouveau.Select the product again.

  • Valider la transaction dans le premier thread.Commit the transaction in first thread.

Si la transaction autorise le comportement, les deux opérations Select obtiendra des résultats différents.If the transaction allows the behavior, the two Select operations will get the different results.

La classe ExchangeValuesThreads illustre la différence entre les transactions Serializable et Snapshot.The ExchangeValuesThreads class demonstrates the difference between the Serializable and Snapshot transaction. Pour la transaction sérialisable, les threads fonctionnera dans l’ordre suivant :For the Serializable transaction, threads will operate in the following order:

  • Dans le premier thread, obtenir le prix de product(ProductId=2) et store dans la variable.In first thread, get the Price of product(ProductId=2) and store in the variable.

  • Dans le premier thread, vous devez mettre à jour le prix de product(ProductId=1) avec le prix de product(ProductId=2).In first thread, update the Price of product(ProductId=1) with the price of product(ProductId=2).

  • Valider la transaction dans le premier thread.Commit the transaction in first thread.

  • Dans le deuxième thread, obtenir le prix de product(ProductId=1) et store dans la variable.In second thread, get the Price of product(ProductId=1) and store in the variable.

  • Dans le deuxième thread, vous devez mettre à jour le prix de product(ProductId=2) avec le prix de product(ProductId=1).In second thread, update the Price of product(ProductId=2) with the price of product(ProductId=1).

  • Valider la transaction dans le deuxième thread.Commit the transaction in second thread.

Désormais les valeurs du prix (ProductId = 1 et ProductId = 2) sont de même que celle du prix de Product(ProductId=2) d’origine.Now the values of the Price(ProductId=1 and ProductId=2) are as same as the original Price of Product(ProductId=2).

Pour la transaction d’instantané, les threads fonctionnera dans l’ordre suivant :For the Snapshot transaction, threads will operate in the following order:

  • Dans le premier thread, obtenir le prix de product(ProductId=2) et store dans la variable ;In first thread, get the Price of product(ProductId=2) and store in the variable;

  • Dans le premier thread, vous devez mettre à jour le prix de product(ProductId=1) avec le prix de product(ProductId=2).In first thread, update the Price of product(ProductId=1) with the price of product(ProductId=2).

  • Dans le deuxième thread, obtenir le prix de product(ProductId=1) à partir de l’instantané et les stocker dans la variable.In second thread, get the Price of product(ProductId=1) from the snapshot and store in the variable.

  • Dans le deuxième thread, vous devez mettre à jour le prix de product(ProductId=2) avec le prix de product(ProductId=1).In second thread, update the Price of product(ProductId=2) with the price of product(ProductId=1).

  • Valider la transaction dans le deuxième thread.Commit the transaction in second thread.

  • Valider la transaction dans le premier thread.Commit the transaction in first thread.

Désormais échanger le prix des produits (ProductId = 1 et ProductId = 2).Now exchange the Price of products(ProductId=1 and ProductId=2).

La classe DirtyReadThreads montre si la transaction spécifique autorise le comportement de lecture erronée.The DirtyReadThreads class demonstrates if the specific transaction allows the Dirty Read behavior. Si la transaction autorise le comportement, les threads fonctionnera dans l’ordre suivant :If the transaction allows the behavior, the threads will operate in the following order:

  • Dans le premier thread, commencer une transaction et ajoutez le value(ProductId=1) quantité.In first thread, begin a transaction and add the Quantity value(ProductId=1).

  • Dans le deuxième thread, lire la valeur de quantité et ajoutez de nouveau la valeur.In the second thread, read the Quantity value and add the value again.

  • Valider la transaction dans le deuxième thread.Commit the transaction in second thread.

  • Restaurer la transaction dans le premier thread.Roll back the transaction in first thread.

Si la transaction autorise le comportement, la valeur de quantité sera ajoutée à deux reprises.If the transaction allows the behavior, the Quantity value will be added twice.

Vous trouverez des projets c# et Visual Basic avec cet exemple de code sur exemples de Code développeur.C# and Visual Basic projects with this code sample can be found on Developer Code Samples.

using System;
using System.Data.SqlClient;
using System.Data;
using System.Threading;
using System.Threading.Tasks;

namespace CSDataIsolationLevel {

   // Use the delegate to call the different threads.
   public delegate void AsyncAccessDatabase(String connString, IsolationLevel level);

   static class DirtyReadThreads {
      public static void DirtyReadFirstThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the DirtyReadFirstThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Update dbo.Products set Quantity=Quantity+100 where ProductId=1;
                    WaitFor Delay '00:00:06';";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "DirtyReadFirst")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }

               if (tran != null)
                  tran.Rollback();
            }
         }

         Console.WriteLine("Exit from the DirtyReadFirstThread.....");
      }

      public static void DirtyReadSecondThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the DirtyReadSecondThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    Declare @qty int;
                    select @qty=Quantity from dbo.Products where ProductId=1;

                    Update dbo.Products set Quantity=@qty+100 where ProductId=1;";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "DirtyReadSecond")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }
               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the DirtyReadSecondThread.....");
      }
   }


   static class NonrepeatableReadThreads {
      public static void NonrepeatableReadFirstThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the NonrepeatableReadFirstThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products
                    where ProductId=1

                    WaitFor Delay '00:00:06';

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products
                    where ProductId=1";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "NonrepeatableReadFirst")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;

                  using (SqlDataReader reader = command.ExecuteReader()) {
                     Boolean isFirstReader = true;
                     do {
                        Console.WriteLine("It's the result of {0} read:", isFirstReader ? "first" : "second");
                        TransactionIsolationLevels.DisplayData(reader);
                        isFirstReader = !isFirstReader;
                     } while (reader.NextResult() && !isFirstReader);
                  }
               }

               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the NonrepeatableReadFirstThread.....");
      }

      public static void NonrepeatableReadSecondThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the NonrepeatableReadSecondThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    Update dbo.Products set Quantity=Quantity+100 where ProductId=1;";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "NonrepeatableReadSecond")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }
               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the NonrepeatableReadSecondThread.....");
      }
   }


   static class PhantomReadThreads {
      public static void PhantomReadFirstThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the PhantomReadFirstThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products

                    WaitFor Delay '00:00:06';

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "PhantomReadFirst")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;

                  using (SqlDataReader reader = command.ExecuteReader()) {
                     Boolean isFirstReader = true;
                     do {
                        Console.WriteLine("It's the result of {0} read:", isFirstReader ? "first" : "second");

                        TransactionIsolationLevels.DisplayData(reader);

                        isFirstReader = !isFirstReader;
                     } while (reader.NextResult() && !isFirstReader);
                  }
               }

               tran.Commit();
            }
         }
         Console.WriteLine("Exit from the PhantomReadFirstThread.....");
      }

      public static void PhantomReadSecondThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the PhantomReadSecondThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) 
                    VALUES (N'White Bike', 843, 1349.00)";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "PhantomReadSecond")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }
               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the PhantomReadSecondThread.....");
      }
   }


   // Demonstrates if the specific transaction allows the following behaviors:
   // 1. Dirty reads;
   // 2. Non-repeatable reads;
   // 3. Phantoms.
   static class TransactionIsolationLevels {
      public static void DemonstrateIsolationLevel(String connString, IsolationLevel level) {
         // Before connect the database, recreate the table.
         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, level, DirtyReadThreads.DirtyReadFirstThread, DirtyReadThreads.DirtyReadSecondThread);
         DisplayData(connString);
         Console.WriteLine();

         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, level, NonrepeatableReadThreads.NonrepeatableReadFirstThread, NonrepeatableReadThreads.NonrepeatableReadSecondThread);
         Console.WriteLine();

         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, level, PhantomReadThreads.PhantomReadFirstThread, PhantomReadThreads.PhantomReadSecondThread);
         Console.WriteLine();
      }

      // Demonstrates if the specific transaction allows the specific behaviors.
      public static void DemonstrateIsolationLevel(String connString, IsolationLevel level,
          AsyncAccessDatabase firstThread, AsyncAccessDatabase secondThread) {
         Task[] tasks ={
                            Task.Factory.StartNew(()=>firstThread(connString, level)),
                            Task.Factory.StartNew(()=>secondThread(connString, level))
                        };

         Task.WaitAll(tasks);
      }

      static class ExchangeValuesThreads {
         public static void ExchangeValuesFirstThread(String connStrig, IsolationLevel level) {
            Console.WriteLine("Begin the ExchangeValuesFirstThread.....");

            using (SqlConnection conn = new SqlConnection(connStrig)) {
               String cmdText = @"Use DbDataIsolationLevel;

                    Declare @price money;
                    select @price=Price from dbo.Products where ProductId=2;

                    Update dbo.Products set Price=@price where ProductId=1;

                    WaitFor Delay '00:00:06'; ";

               conn.Open();
               using (SqlTransaction tran = conn.BeginTransaction(level, "ExchangeValuesFirst")) {

                  using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                     command.Transaction = tran;
                     command.ExecuteNonQuery();
                  }

                  tran.Commit();
               }
            }

            Console.WriteLine("Exit from the ExchangeValuesFirstThread.....");
         }

         public static void ExchangeValuesSecondThread(String connStrig, IsolationLevel level) {
            Console.WriteLine("Begin the ExchangeValuesSecondThread.....");

            using (SqlConnection conn = new SqlConnection(connStrig)) {
               String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    Declare @price money;
                    select @price=Price from dbo.Products where ProductId=1;

                    Update dbo.Products set Price=@price where ProductId=2;";

               conn.Open();

               using (SqlTransaction tran = conn.BeginTransaction(level, "ExchangeValuesSecond")) {
                  using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                     command.Transaction = tran;
                     command.ExecuteNonQuery();
                  }
                  tran.Commit();
               }
            }

            Console.WriteLine("Exit from the ExchangeValuesSecondThread.....");
         }
      }

      // Demonstrates the difference between the Serializable and Snapshot transaction
      public static void DemonstrateBetweenSnapshotAndSerializable(String connString) {
         OperateDatabase.CreateTable(connString);

         Console.WriteLine("Exchange Vaules in the Snapshot transaction:");
         DemonstrateIsolationLevel(connString, IsolationLevel.Snapshot,
             ExchangeValuesThreads.ExchangeValuesFirstThread,
             ExchangeValuesThreads.ExchangeValuesSecondThread);
         DisplayData(connString);
         Console.WriteLine();

         Console.WriteLine("Cannot Exchange Vaules in the Serializable transaction:");
         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, IsolationLevel.Serializable,
             ExchangeValuesThreads.ExchangeValuesFirstThread,
             ExchangeValuesThreads.ExchangeValuesSecondThread);
         DisplayData(connString);
      }

      public static void DisplayData(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products";

            conn.Open();

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               using (SqlDataReader reader = command.ExecuteReader()) {
                  DisplayData(reader);
               }
            }
         }
      }

      public static void DisplayData(SqlDataReader reader) {
         Boolean isFirst = true;

         while (reader.Read()) {
            if (isFirst) {
               isFirst = false;

               for (int i = 0; i < reader.FieldCount; i++)
                  Console.Write("{0,-12}   ", reader.GetName(i));
               Console.WriteLine();
            }

            for (int i = 0; i < reader.FieldCount; i++)
               Console.Write("{0,-12}   ", reader[i]);
            Console.WriteLine();
         }
      }
   }

   // This class includes database operations. If there's no database 'DbDataIsolationLevel', create the database.
   static class OperateDatabase {
      public static Boolean CreateDatabase(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use Master;

                                     if Db_Id('DbDataIsolationLevel') is null
                                      create Database [DbDataIsolationLevel];";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }

            Console.WriteLine("Create the Database 'DbDataIsolationLevel'");
         }

         return true;
      }


      // If there's no table [dbo].[Products] in DbDataIsolationLevel, create the table; or recreate it.
      public static Boolean CreateTable(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use DbDataIsolationLevel

                                    if Object_ID('[dbo].[Products]') is not null
                                    drop table [dbo].[Products]

                                    Create Table [dbo].[Products]
                                    (
                                    [ProductId] int IDENTITY(1,1) primary key,
                                    [ProductName] NVarchar(100) not null,
                                    [Quantity] int null,
                                    [Price] money null
                                    )";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }
         }

         return InsertRows(connString);
      }

      // Insert some rows into [dbo].[Products] table.
      public static Boolean InsertRows(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use DbDataIsolationLevel

                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Blue Bike', 365,1075.00)
                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Red Bike', 159, 1299.00)
                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Black Bike', 638, 1159.00)";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }
         }
         return true;
      }

      // Turn on or off 'ALLOW_SNAPSHOT_ISOLATION'
      public static Boolean SetSnapshot(String connString, Boolean isOpen) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = null;

            if (isOpen)
               cmdText = @"ALTER DATABASE DbDataIsolationLevel SET ALLOW_SNAPSHOT_ISOLATION ON";
            else
               cmdText = @"ALTER DATABASE DbDataIsolationLevel SET ALLOW_SNAPSHOT_ISOLATION OFF";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }
         }

         return true;
      }
   }
   class Program {
      static void Main(string[] args) {
         String connString = "Data Source=(local);Initial Catalog=master;Integrated Security=True;Asynchronous Processing=true;";

         OperateDatabase.CreateDatabase(connString);
         Console.WriteLine();

         Console.WriteLine("Demonstrate the ReadUncommitted transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.ReadUncommitted);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the ReadCommitted transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.ReadCommitted);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the RepeatableRead transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.RepeatableRead);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the Serializable transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.Serializable);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the Snapshot transaction: ");
         OperateDatabase.SetSnapshot(connString, true);
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.Snapshot);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the difference between the Snapshot and Serializable transactions:");
         TransactionIsolationLevels.DemonstrateBetweenSnapshotAndSerializable(connString);
         OperateDatabase.SetSnapshot(connString, false);
         Console.WriteLine();
      }
   }
}
Imports System.Data.SqlClient
Imports System.Data
Imports System.Threading
Imports System.Threading.Tasks

Namespace CSDataIsolationLevel

   ' Use the delegate to call the different threads.
   Public Delegate Sub AsyncAccessDatabase(connString As [String], level As IsolationLevel)

   NotInheritable Class DirtyReadThreads
      Private Sub New()
      End Sub
      Public Shared Sub DirtyReadFirstThread(connStrig As [String], level As IsolationLevel)
         Console.WriteLine("Begin the DirtyReadFirstThread.....")

         Using conn As New SqlConnection(connStrig)
            Dim cmdText As [String] = "Use DbDataIsolationLevel; " & vbCr & vbLf & vbCr & vbLf &
                "Update dbo.Products set Quantity=Quantity+100 where ProductId=1;" & vbCr & vbLf &
                "WaitFor Delay '00:00:06';"

            conn.Open()

            Using tran As SqlTransaction = conn.BeginTransaction(level, "DirtyReadFirst")
               Using command As New SqlCommand(cmdText, conn)
                  command.Transaction = tran
                  command.ExecuteNonQuery()
               End Using

               If tran IsNot Nothing Then
                  tran.Rollback()
               End If
            End Using
         End Using

         Console.WriteLine("Exit from the DirtyReadFirstThread.....")
      End Sub

      Public Shared Sub DirtyReadSecondThread(connStrig As [String], level As IsolationLevel)
         Console.WriteLine("Begin the DirtyReadSecondThread.....")

         Using conn As New SqlConnection(connStrig)
            Dim cmdText As [String] = "Use DbDataIsolationLevel;" & vbCr & vbLf & vbCr & vbLf &
                "WaitFor Delay '00:00:03'; " & vbCr & vbLf & vbCr & vbLf &
                "Declare @qty int;" & vbCr & vbLf &
                "select @qty=Quantity from dbo.Products where ProductId=1;" & vbCr & vbLf & vbCr & vbLf &
                "Update dbo.Products set Quantity=@qty+100 where ProductId=1;"

            conn.Open()

            Using tran As SqlTransaction = conn.BeginTransaction(level, "DirtyReadSecond")
               Using command As New SqlCommand(cmdText, conn)
                  command.Transaction = tran
                  command.ExecuteNonQuery()
               End Using
               tran.Commit()
            End Using
         End Using

         Console.WriteLine("Exit from the DirtyReadSecondThread.....")
      End Sub
   End Class


   NotInheritable Class NonrepeatableReadThreads
      Private Sub New()
      End Sub
      Public Shared Sub NonrepeatableReadFirstThread(connStrig As [String], level As IsolationLevel)
         Console.WriteLine("Begin the NonrepeatableReadFirstThread.....")

         Using conn As New SqlConnection(connStrig)
            Dim cmdText As [String] = "Use DbDataIsolationLevel; " & vbCr & vbLf & vbCr & vbLf &
                "Select ProductId,ProductName,Quantity,Price" & vbCr & vbLf &
                "from dbo.Products" & vbCr & vbLf &
                "where ProductId=1" & vbCr & vbLf & vbCr & vbLf &
                "WaitFor Delay '00:00:06';" & vbCr & vbLf & vbCr & vbLf &
                "Select ProductId,ProductName,Quantity,Price" & vbCr & vbLf &
                "from dbo.Products" & vbCr & vbLf &
                "where ProductId=1"

            conn.Open()

            Using tran As SqlTransaction = conn.BeginTransaction(level, "NonrepeatableReadFirst")
               Using command As New SqlCommand(cmdText, conn)
                  command.Transaction = tran

                  Using reader As SqlDataReader = command.ExecuteReader()
                     Dim isFirstReader As [Boolean] = True
                     Do
                        Console.WriteLine("It's the result of {0} read:", If(isFirstReader, "first", "second"))
                        TransactionIsolationLevels.DisplayData(reader)
                        isFirstReader = Not isFirstReader
                     Loop While reader.NextResult() AndAlso Not isFirstReader
                  End Using
               End Using

               tran.Commit()
            End Using
         End Using

         Console.WriteLine("Exit from the NonrepeatableReadFirstThread.....")
      End Sub

      Public Shared Sub NonrepeatableReadSecondThread(connStrig As [String], level As IsolationLevel)
         Console.WriteLine("Begin the NonrepeatableReadSecondThread.....")

         Using conn As New SqlConnection(connStrig)
            Dim cmdText As [String] = "Use DbDataIsolationLevel;" & vbCr & vbLf & vbCr & vbLf &
                "WaitFor Delay '00:00:03'; " & vbCr & vbLf & vbCr & vbLf &
                "Update dbo.Products set Quantity=Quantity+100 where ProductId=1;"

            conn.Open()

            Using tran As SqlTransaction = conn.BeginTransaction(level, "NonrepeatableReadSecond")
               Using command As New SqlCommand(cmdText, conn)
                  command.Transaction = tran
                  command.ExecuteNonQuery()
               End Using
               tran.Commit()
            End Using
         End Using

         Console.WriteLine("Exit from the NonrepeatableReadSecondThread.....")
      End Sub
   End Class


   NotInheritable Class PhantomReadThreads
      Private Sub New()
      End Sub
      Public Shared Sub PhantomReadFirstThread(connStrig As [String], level As IsolationLevel)
         Console.WriteLine("Begin the PhantomReadFirstThread.....")

         Using conn As New SqlConnection(connStrig)
            Dim cmdText As [String] = "Use DbDataIsolationLevel; " & vbCr & vbLf & vbCr & vbLf &
                "Select ProductId,ProductName,Quantity,Price" & vbCr & vbLf &
                "from dbo.Products" & vbCr & vbLf & vbCr & vbLf &
                "WaitFor Delay '00:00:06';" & vbCr & vbLf & vbCr & vbLf &
                "Select ProductId,ProductName,Quantity,Price" & vbCr & vbLf &
                "from dbo.Products"

            conn.Open()

            Using tran As SqlTransaction = conn.BeginTransaction(level, "PhantomReadFirst")
               Using command As New SqlCommand(cmdText, conn)
                  command.Transaction = tran

                  Using reader As SqlDataReader = command.ExecuteReader()
                     Dim isFirstReader As [Boolean] = True
                     Do
                        Console.WriteLine("It's the result of {0} read:", If(isFirstReader, "first", "second"))

                        TransactionIsolationLevels.DisplayData(reader)

                        isFirstReader = Not isFirstReader
                     Loop While reader.NextResult() AndAlso Not isFirstReader
                  End Using
               End Using

               tran.Commit()
            End Using
         End Using
         Console.WriteLine("Exit from the PhantomReadFirstThread.....")
      End Sub

      Public Shared Sub PhantomReadSecondThread(connStrig As [String], level As IsolationLevel)
         Console.WriteLine("Begin the PhantomReadSecondThread.....")

         Using conn As New SqlConnection(connStrig)
            Dim cmdText As [String] = "Use DbDataIsolationLevel;" & vbCr & vbLf & vbCr & vbLf &
                "WaitFor Delay '00:00:03'; " & vbCr & vbLf & vbCr & vbLf &
                "INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) " & vbCr & vbLf &
                "VALUES (N'White Bike', 843, 1349.00)"

            conn.Open()

            Using tran As SqlTransaction = conn.BeginTransaction(level, "PhantomReadSecond")
               Using command As New SqlCommand(cmdText, conn)
                  command.Transaction = tran
                  command.ExecuteNonQuery()
               End Using
               tran.Commit()
            End Using
         End Using

         Console.WriteLine("Exit from the PhantomReadSecondThread.....")
      End Sub
   End Class


   ' Demonstrates if the specific transaction allows the following behaviors:
   ' 1. Dirty reads;
   ' 2. Non-repeatable reads;
   ' 3. Phantoms.
   NotInheritable Class TransactionIsolationLevels
      Private Sub New()
      End Sub
      Public Shared Sub DemonstrateIsolationLevel(connString As [String], level As IsolationLevel)
         ' Before connect the database, recreate the table.
         OperateDatabase.CreateTable(connString)
         DemonstrateIsolationLevel(connString, level, AddressOf DirtyReadThreads.DirtyReadFirstThread, AddressOf DirtyReadThreads.DirtyReadSecondThread)
         DisplayData(connString)
         Console.WriteLine()

         OperateDatabase.CreateTable(connString)
         DemonstrateIsolationLevel(connString, level, AddressOf NonrepeatableReadThreads.NonrepeatableReadFirstThread, AddressOf NonrepeatableReadThreads.NonrepeatableReadSecondThread)
         Console.WriteLine()

         OperateDatabase.CreateTable(connString)
         DemonstrateIsolationLevel(connString, level, AddressOf PhantomReadThreads.PhantomReadFirstThread, AddressOf PhantomReadThreads.PhantomReadSecondThread)
         Console.WriteLine()
      End Sub

      ' Demonstrates if the specific transaction allows the specific behaviors.
      Public Shared Sub DemonstrateIsolationLevel(connString As [String], level As IsolationLevel, firstThread As AsyncAccessDatabase, secondThread As AsyncAccessDatabase)
         ' Dim tasks As Task() = {Task.Factory.StartNew(Function() firstThread(connString, level)), Task.Factory.StartNew(Function() secondThread(connString, level))}

         Dim tasks() As Task = {
                         Task.Factory.StartNew(Sub() firstThread(connString, level)),
                         Task.Factory.StartNew(Sub() secondThread(connString, level))
                                        }

         Task.WaitAll(tasks)
      End Sub

      Private NotInheritable Class ExchangeValuesThreads
         Private Sub New()
         End Sub
         Public Shared Sub ExchangeValuesFirstThread(connStrig As [String], level As IsolationLevel)
            Console.WriteLine("Begin the ExchangeValuesFirstThread.....")

            Using conn As New SqlConnection(connStrig)
               Dim cmdText As [String] = "Use DbDataIsolationLevel;" & vbCr & vbLf & vbCr & vbLf &
                   "Declare @price money;" & vbCr & vbLf &
                   "select @price=Price from dbo.Products where ProductId=2;" & vbCr & vbLf & vbCr & vbLf &
                   "Update dbo.Products set Price=@price where ProductId=1;" & vbCr & vbLf & vbCr & vbLf &
                   "WaitFor Delay '00:00:06'; "

               conn.Open()
               Using tran As SqlTransaction = conn.BeginTransaction(level, "ExchangeValuesFirst")

                  Using command As New SqlCommand(cmdText, conn)
                     command.Transaction = tran
                     command.ExecuteNonQuery()
                  End Using

                  tran.Commit()
               End Using
            End Using

            Console.WriteLine("Exit from the ExchangeValuesFirstThread.....")
         End Sub

         Public Shared Sub ExchangeValuesSecondThread(connStrig As [String], level As IsolationLevel)
            Console.WriteLine("Begin the ExchangeValuesSecondThread.....")

            Using conn As New SqlConnection(connStrig)
               Dim cmdText As [String] = "Use DbDataIsolationLevel;" & vbCr & vbLf & vbCr & vbLf &
                   "WaitFor Delay '00:00:03'; " & vbCr & vbLf & vbCr & vbLf &
                   "Declare @price money;" & vbCr & vbLf &
                   "select @price=Price from dbo.Products where ProductId=1;" & vbCr & vbLf & vbCr & vbLf &
                   "Update dbo.Products set Price=@price where ProductId=2;"

               conn.Open()

               Using tran As SqlTransaction = conn.BeginTransaction(level, "ExchangeValuesSecond")
                  Using command As New SqlCommand(cmdText, conn)
                     command.Transaction = tran
                     command.ExecuteNonQuery()
                  End Using
                  tran.Commit()
               End Using
            End Using

            Console.WriteLine("Exit from the ExchangeValuesSecondThread.....")
         End Sub
      End Class

      ' Demonstrates the difference between the Serializable and Snapshot transaction
      Public Shared Sub DemonstrateBetweenSnapshotAndSerializable(connString As [String])
         OperateDatabase.CreateTable(connString)

         Console.WriteLine("Exchange Vaules in the Snapshot transaction:")
         DemonstrateIsolationLevel(connString, IsolationLevel.Snapshot, AddressOf ExchangeValuesThreads.ExchangeValuesFirstThread, AddressOf ExchangeValuesThreads.ExchangeValuesSecondThread)
         DisplayData(connString)
         Console.WriteLine()

         Console.WriteLine("Cannot Exchange Vaules in the Serializable transaction:")
         OperateDatabase.CreateTable(connString)
         DemonstrateIsolationLevel(connString, IsolationLevel.Serializable, AddressOf ExchangeValuesThreads.ExchangeValuesFirstThread, AddressOf ExchangeValuesThreads.ExchangeValuesSecondThread)
         DisplayData(connString)
      End Sub

      Public Shared Sub DisplayData(connString As [String])
         Using conn As New SqlConnection(connString)
            Dim cmdText As [String] = "Use DbDataIsolationLevel; " & vbCr & vbLf & vbCr & vbLf &
                "Select ProductId,ProductName,Quantity,Price" & vbCr & vbLf &
                "from dbo.Products"

            conn.Open()

            Using command As New SqlCommand(cmdText, conn)
               Using reader As SqlDataReader = command.ExecuteReader()
                  DisplayData(reader)
               End Using
            End Using
         End Using
      End Sub

      Public Shared Sub DisplayData(reader As SqlDataReader)
         Dim isFirst As [Boolean] = True

         While reader.Read()
            If isFirst Then
               isFirst = False

               For i As Integer = 0 To reader.FieldCount - 1
                  Console.Write("{0,-12}   ", reader.GetName(i))
               Next
               Console.WriteLine()
            End If

            For i As Integer = 0 To reader.FieldCount - 1
               Console.Write("{0,-12}   ", reader(i))
            Next
            Console.WriteLine()
         End While
      End Sub
   End Class

   ' This class includes database operations. If there's no database 'DbDataIsolationLevel', create the database.
   NotInheritable Class OperateDatabase
      Private Sub New()
      End Sub
      Public Shared Function CreateDatabase(connString As [String]) As [Boolean]
         Using conn As New SqlConnection(connString)
            Dim cmdText As [String] = "Use Master;" & vbCr & vbLf & vbCr & vbLf &
                "if Db_Id('DbDataIsolationLevel') is null" & vbCr & vbLf &
                "create Database [DbDataIsolationLevel];"

            Using command As New SqlCommand(cmdText, conn)
               conn.Open()
               command.ExecuteNonQuery()
            End Using

            Console.WriteLine("Create the Database 'DbDataIsolationLevel'")
         End Using

         Return True
      End Function


      ' If there's no table [dbo].[Products] in DbDataIsolationLevel, create the table; or recreate it.
      Public Shared Function CreateTable(connString As [String]) As [Boolean]
         Using conn As New SqlConnection(connString)
            Dim cmdText As [String] = "Use DbDataIsolationLevel" & vbCr & vbLf & vbCr & vbLf &
                "if Object_ID('[dbo].[Products]') is not null" & vbCr & vbLf &
                "drop table [dbo].[Products]" & vbCr & vbLf & vbCr & vbLf &
                "Create Table [dbo].[Products]" & vbCr & vbLf &
                "(" & vbCr & vbLf &
                "[ProductId] int IDENTITY(1,1) primary key," & vbCr & vbLf &
                "[ProductName] NVarchar(100) not null," & vbCr & vbLf &
                "[Quantity] int null," & vbCr & vbLf &
                "[Price] money null" & vbCr & vbLf & "                                    )"

            Using command As New SqlCommand(cmdText, conn)
               conn.Open()
               command.ExecuteNonQuery()
            End Using
         End Using

         Return InsertRows(connString)
      End Function

      ' Insert some rows into [dbo].[Products] table.
      Public Shared Function InsertRows(connString As [String]) As [Boolean]
         Using conn As New SqlConnection(connString)
            Dim cmdText As [String] = "Use DbDataIsolationLevel" & vbCr & vbLf & vbCr & vbLf &
                "INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Blue Bike', 365,1075.00)" & vbCr & vbLf &
                "INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Red Bike', 159, 1299.00)" & vbCr & vbLf &
                "INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Black Bike', 638, 1159.00)"

            Using command As New SqlCommand(cmdText, conn)
               conn.Open()
               command.ExecuteNonQuery()
            End Using
         End Using
         Return True
      End Function

      ' Turn on or off 'ALLOW_SNAPSHOT_ISOLATION'
      Public Shared Function SetSnapshot(connString As [String], isOpen As [Boolean]) As [Boolean]
         Using conn As New SqlConnection(connString)
            Dim cmdText As [String] = Nothing

            If isOpen Then
               cmdText = "ALTER DATABASE DbDataIsolationLevel SET ALLOW_SNAPSHOT_ISOLATION ON"
            Else
               cmdText = "ALTER DATABASE DbDataIsolationLevel SET ALLOW_SNAPSHOT_ISOLATION OFF"
            End If

            Using command As New SqlCommand(cmdText, conn)
               conn.Open()
               command.ExecuteNonQuery()
            End Using
         End Using

         Return True
      End Function
   End Class
   Class Program
      Public Shared Sub Main(args As String())
         Dim connString As [String] = "Data Source=(local);Initial Catalog=master;Integrated Security=True;Asynchronous Processing=true;"

         OperateDatabase.CreateDatabase(connString)
         Console.WriteLine()

         Console.WriteLine("Demonstrate the ReadUncommitted transaction: ")
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString, System.Data.IsolationLevel.ReadUncommitted)
         Console.WriteLine("-----------------------------------------------")

         Console.WriteLine("Demonstrate the ReadCommitted transaction: ")
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString, System.Data.IsolationLevel.ReadCommitted)
         Console.WriteLine("-----------------------------------------------")

         Console.WriteLine("Demonstrate the RepeatableRead transaction: ")
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString, System.Data.IsolationLevel.RepeatableRead)
         Console.WriteLine("-----------------------------------------------")

         Console.WriteLine("Demonstrate the Serializable transaction: ")
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString, System.Data.IsolationLevel.Serializable)
         Console.WriteLine("-----------------------------------------------")

         Console.WriteLine("Demonstrate the Snapshot transaction: ")
         OperateDatabase.SetSnapshot(connString, True)
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString, System.Data.IsolationLevel.Snapshot)
         Console.WriteLine("-----------------------------------------------")

         Console.WriteLine("Demonstrate the difference between the Snapshot and Serializable transactions:")
         TransactionIsolationLevels.DemonstrateBetweenSnapshotAndSerializable(connString)
         OperateDatabase.SetSnapshot(connString, False)
         Console.WriteLine()
      End Sub
   End Class
End Namespace

Remarques

Le IsolationLevel valeurs sont utilisées par un fournisseur de données .NET lors de l’exécution d’une transaction.The IsolationLevel values are used by a .NET data provider when performing a transaction.

Le IsolationLevel restera en vigueur jusqu'à ce qu’explicitement modifiée, mais il peut être modifié à tout moment.The IsolationLevel remains in effect until explicitly changed, but it can be changed at any time. La nouvelle valeur est utilisée au moment de l’exécution, pas les temps d’analyse.The new value is used at execution time, not parse time. Dans ce cas lors d’une transaction, le comportement attendu du serveur consiste à appliquer le nouveau niveau de verrouillage pour toutes les instructions restantes.If changed during a transaction, the expected behavior of the server is to apply the new locking level to all statements remaining.

Lorsque vous utilisez OdbcTransaction, si vous ne définissez pas OdbcTransaction.IsolationLevel ou définissez-le sur Unspecified, la transaction s’exécute en fonction du niveau d’isolement déterminé par le pilote en cours d’utilisation.When using OdbcTransaction, if you do not set OdbcTransaction.IsolationLevel or you set it to Unspecified, the transaction executes according to the isolation level determined by the driver in use.

S’applique à