[ Team LiB ] Recipe 6.14 Specifying LockingHintsinaSQLServerDatabase Problem You need to pessimistically lock rows in an underlying SQLServer database. Solution Use SQLServerlockinghints from ADO.NET. The sample code contains three event handlers: Start Tran Button.Click Creates aSQL SELECT statement to retrieve the Orders table from the Northwind database. Alocking hint, either UPDLOCK or HOLDLOCK, is added to the statement as specified. A Connection is opened and a Transaction started on it with an isolation level of ReadCommitted. A DataAdapter is used on the transacted connection to fill a DataTable. A CommandBuilder is created to generate updating logic. The default view of the table is bound to the data grid on the form. Cancel Button.Click Clears the data grid, rolls back the transaction, and closes the connection. Form.Closing Rolls back the transaction if it exists and closes the connection. The C# code is shown in Example 6-39 . Example 6-39. File: UsingLockingHintsForPessimisticLockingForm.cs // Namespaces, variables, and constants using System; using System.Configuration; 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; String sqlText = "SELECT * FROM Orders WITH "; // Add pessimistic locking as specified by user. if(updLockRadioButton.Checked) sqlText += "(UPDLOCK)"; else if(holdLockRadioButton.Checked) sqlText += "(HOLDLOCK)"; // Create connection. conn = new SqlConnection( ConfigurationSettings.AppSettings["Sql_ConnectString"]); conn.Open( ); // Start the transaction. tran = conn.BeginTransaction(IsolationLevel.ReadCommitted); // Create the command. SqlCommand cmd = new SqlCommand(sqlText, conn, tran); // Create the DataAdapter and CommandBuilder. SqlDataAdapter da = new SqlDataAdapter(cmd); SqlCommandBuilder cb = new SqlCommandBuilder(da); // Fill table using the DataAdapter. 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; // Unbind the table from the grid. dataGrid.DataSource = null; // Roll back the transaction and close the connection. tran.Rollback( ); conn.Close( ); startButton.Enabled = true; } Discussion A lock is an object indicating that a user has a dependency on a resource. Locks ensure transactional integrity and database consistency by preventing other users from changing data being read by a user and preventing users from reading data being changed by a user. Locks are acquired and released by user actions; they are managed internally by database software. Alocking hint can be specified with SELECT, INSERT, DELETE, and UPDATE statements to instruct SQLServer as to the type of lock to use. You can use lockinghints when you need control over locks acquired on objects. The SQLServer Optimizer automatically determines correct locking; hints should be used only when necessary. Lockinghints override the current transaction isolation level for the session. Alocking hint is specified following the FROM clause using a WITH clause. The hint is specified within parentheses and multiple hints are separated by commas. Tables Table 6-21 , Table 6-22, and Table 6-23 describe the different lockinghints that you can use, categorized according to their function. Table 6-21. SQLServerlockinghints for isolation level Locking hint Description HOLDLOCK Hold a shared lock until the transaction is completed instead of releasing it as soon as the required object—table, row, or data page—is no longer needed. NOLOCK Do not issue shared locks and do not recognize exclusive locks. Applies only to the SELECT statement. READCOMMITTED Use the same locking as a transaction with an isolation level of READ COMMITTED. READUNCOMMITTED Same as NOLOCK. REPEATABLEREAD Use the same locking as a transaction with an isolation level of REPEATABLE READ. SERIALIZABLE Use the same locking as a transaction with an isolation level of SERIALIZABLE. Table 6-22. SQLServerlockinghints for granularity Locking hint Description NOLOCK Do not issue shared locks and do not recognize exclusive locks. Applies only to the SELECT statement. PAGLOCK Use page locks where a single table lock would normally be used. ROWLOCK Use row-level locking instead of page-level and table-level locking. TABLOCK Use table-level locking instead of row-level and page-level locking. By default, the lock is held until the end of the statement. TABLOCKX Use an exclusive table lock preventing other users from reading or updating the table. By default, the lock is held until the end of the statement. Table 6-23. SQLServerLockingHints for Other Functions Locking hint Description READPAST Skip locked rows that would ordinarily appear in the result set rather than blocking the transaction by waiting for other transactions to release locks on those rows. Applies only to transactions with an isolation level of READ COMMITTED. Applies only to the SELECT statement. UPDLOCK Use update locks instead of shared locks when reading a table. This allows you to read data and later update it with a guarantee that it has not changed since you last read it while other users are not blocked from reading the data. Cannot be used with NOLOCK or XLOCK. XLOCK Use an exclusive lock that is held until the end of the transaction on all data processed by the statement. Can be specified with either PAGLOCK or TABLOCK granularity. Cannot be used with either NOLOCK or UPDLOCK. There are a number ways to get information about database locks: • The system stored procedure sp_lock returns a result set containing all active locks. • The syslockinfo table in the master database contains information about all granted, converting, and waiting lock requests. It is a denormalized view of the data structures used internally by the lock manager. • The SQLServer Profiler can be used to monitor and record locking information. • The Windows Performance Monitor has aSQLServer Locks Object counter that can be used to monitor lock activity. For more information about database locks, using locking hints, or monitoring database locks, see Microsoft SQLServer Books Online. [ Team LiB ] . SqlDataAdapter da = new SqlDataAdapter(cmd); SqlCommandBuilder cb = new SqlCommandBuilder(da); // Fill table using the DataAdapter. DataTable dt = new DataTable(. Team LiB ] Recipe 6.14 Specifying Locking Hints in a SQL Server Database Problem You need to pessimistically lock rows in an underlying SQL Server database.