[ Team LiB ] |
Recipe 6.12 Using Transaction Isolation Levels to Protect DataProblemYou want to effectively use transaction isolation levels to ensure data consistency for a range of data rows. SolutionSet and use isolation levels as shown in the following example. The sample code contains three event handlers:
The C# code is shown in Example 6-30. Example 6-30. File: TransactionIsolationLevelsForm.cs// Namespaces, variables, and constants using System; using System.Configuration; using System.Windows.Forms; using System.Data; using System.Data.SqlClient; private SqlConnection conn; private SqlTransaction tran; // . . . private void startButton_Click(object sender, System.EventArgs e) { startButton.Enabled = false; // Get the user-defined isolation level. IsolationLevel il = IsolationLevel.Unspecified; if(chaosRadioButton.Checked) il = IsolationLevel.Chaos; else if(readCommittedRadioButton.Checked) il = IsolationLevel.ReadCommitted; else if(readUncommittedRadioButton.Checked) il = IsolationLevel.ReadUncommitted; else if(repeatableReadRadioButton.Checked) il = IsolationLevel.RepeatableRead; else if(serializableRadioButton.Checked) il = IsolationLevel.Serializable; else if(unspecifiedRadioButton.Checked) il = IsolationLevel.Unspecified; // Open a connection. conn = new SqlConnection( ConfigurationSettings.AppSettings["Sql_ConnectString"]); conn.Open( ); try { // Start a transaction. tran = conn.BeginTransaction(il); } catch(Exception ex) { // Could not start the transaction. Close the connection. conn.Close( ); MessageBox.Show(ex.Message,"Transaction Isolation Levels", MessageBoxButtons.OK, MessageBoxIcon.Error); startButton.Enabled = true; return; } String sqlText = "SELECT * FROM Orders"; // Create a command using the transaction. SqlCommand cmd = new SqlCommand(sqlText, conn, tran); // Create a DataAdapter to retrieve all Orders. SqlDataAdapter da = new SqlDataAdapter(cmd); // Define a CommandBuilder for the DataAdapter. SqlCommandBuilder cb = new SqlCommandBuilder(da); // Fill table with Orders. DataTable dt = new DataTable( ); da.Fill(dt); // Bind the default view of the table to the grid. dataGrid.DataSource = dt.DefaultView; cancelButton.Enabled = true; dataGrid.ReadOnly = false; } private void cancelButton_Click(object sender, System.EventArgs e) { cancelButton.Enabled = false; dataGrid.ReadOnly = true; // Roll back the transaction and close the connection. tran.Rollback( ); conn.Close( ); // Unbind the grid. dataGrid.DataSource = null; startButton.Enabled = true; } private void UsingLockingHintsForPessimisticLockingForm_Closing( object sender, System.ComponentModel.CancelEventArgs e) { // Roll back the transaction and close the connection. tran.Rollback( ); conn.Close( ); } DiscussionThe isolation level specifies the transaction locking behavior for a connection. It determines what changes made to data within a transaction are visible outside of the transaction while the transaction is uncommitted. Concurrency violations occur when multiple users or processes attempt to modify the same data in a database at the same time without locking. Table 6-16 describes concurrency problems.
Locks ensure transactional integrity and maintain database consistency by controlling how resources can be accessed by concurrent transactions. A lock is an object indicating that a user has a dependency on a resource. It prevents other users from performing operations that would adversely affect the locked resources. Locks are acquired and released by user actions; they are managed internally by database software. Table 6-17 lists and describes resource lock modes used by ADO.NET.
Isolation level defines the degree to which one transaction must be isolated from other transactions. A higher isolation level increases data correctness but decreases concurrent access to data. Table 6-18 describes the different isolations levels supported by ADO.NET. The first four levels are listed in order of increasing isolation.
In ADO.NET, the isolation level can be set by creating the transaction using an overload of the BeginTransaction( ) method of the Command or by setting the IsolationLevel property of an existing Transaction object. The default isolation level is ReadCommitted. Parallel transactions are not supported, so the isolation level applies to the entire transaction. It can be changed programmatically at any time. If the isolation level is changed within a transaction, the new level applies to all statements remaining in the transaction. |
[ Team LiB ] |