1. Trang chủ
  2. » Công Nghệ Thông Tin

OReilly ADO Dot NET Cookbook Sep 2003 ISBN 0596004397

11 45 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 11
Dung lượng 284,08 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Insert Button.Click Inserts user-entered data for two Categories records into the Northwind database within a manual transaction.. Once started, the transaction remains in a pending stat

Trang 1

Problem

You need to explicitly begin, control, and end a transaction

within a NET application

Solution

Use the Connection object with structured exceptions (try catch finally)

The sample code contains two event handlers:

Form.Load

Sets up the sample by filling a DataTable with the

Categories table from the Northwind sample database The default view of the table is bound to a data grid on the

form

Insert Button.Click

Inserts user-entered data for two Categories records into the Northwind database within a manual transaction If

either record insert fails, both inserts are rolled back;

otherwise, both record inserts are committed

The C# code is shown in Example 6-3

Example 6-3 File: ManualTransactionForm.cs

Trang 2

using System;

using System.Configuration;

using System.Windows.Forms;

using System.Data;

using System.Data.SqlClient;

private const String CATEGORIES_TABLE = "Categories";

private DataTable dt;

private SqlDataAdapter da;

//

private void ManualTransactionForm_Load(object sender, System.EventArgs e) {

// Fill the categories table

String sqlText = "SELECT CategoryID, CategoryName, " +

"Description FROM Categories";

da = new SqlDataAdapter(sqlText,

ConfigurationSettings.AppSettings["Sql_ConnectString"]);

dt = new DataTable(CATEGORIES_TABLE);

da.FillSchema(dt, SchemaType.Source);

da.Fill(dt);

// Bind the default view of the table to the grid

dataGrid.DataSource = dt.DefaultView;

}

private void insertButton_Click(object sender, System.EventArgs e)

{

String sqlText = "INSERT " + CATEGORIES_TABLE + " "+

"(CategoryName, Description) VALUES " +

"(@CategoryName, @Description)";

// Create the connection

SqlConnection conn = new SqlConnection(

Trang 3

ConfigurationSettings.AppSettings["Sql_ConnectString"]); // Create the transaction

conn.Open( );

SqlTransaction tran = conn.BeginTransaction( );

// Create command in the transaction with parameters

SqlCommand cmd = new SqlCommand(sqlText, conn, tran);

cmd.Parameters.Add(new SqlParameter("@CategoryName",

SqlDbType.NVarChar, 15));

cmd.Parameters.Add(new SqlParameter("@Description",

SqlDbType.NVarChar, 100));

try

{

// Insert the records into the table

if (categoryName1TextBox.Text.Trim( ).Length == 0)

// If CategoryName is empty, make it null (invalid) cmd.Parameters["@CategoryName"].Value = DBNull.Value; else

cmd.Parameters["@CategoryName"].Value =

categoryName1TextBox.Text;

cmd.Parameters["@Description"].Value =

description1TextBox.Text;

cmd.ExecuteNonQuery( );

if (categoryName2TextBox.Text.Trim( ).Length == 0)

cmd.Parameters["@CategoryName"].Value = DBNull.Value; else

cmd.Parameters["@CategoryName"].Value =

categoryName2TextBox.Text;

cmd.Parameters["@Description"].Value =

description2TextBox.Text;

cmd.ExecuteNonQuery( );

// If okay to here, commit the transaction

tran.Commit( );

Trang 4

}

catch (Exception ex)

{

// Exception occurred Roll back the transaction tran.Rollback( );

MessageBox.Show(ex.Message + Environment.NewLine + "Transaction rollback.");

}

finally

{

conn.Close( );

}

// Refresh the data

da.Fill(dt);

}

Discussion

Manual transactions allow control over the transaction boundary

through explicit commands to start and end the transaction

There is no built-in support for distributed transactions spanning

multiple resources with manual transactions

.NET data providers make available objects to enable manual

transactions The Connection object has a BeginTransaction(

) method that is used to start a transaction If successful, the

method returns a Transaction object that is used to perform

all subsequent actions associated with the transaction, such as

committing or aborting Calling the BeginTransaction( )

method does not implicitly cause all subsequent commands to

execute within the transaction The Transaction property of

the Command object must be set to a transaction that has

already been started for the command to execute within the

Trang 5

Once started, the transaction remains in a pending state until it

is explicitly committed or rolled back using the Commit( ) or

Rollback( ) methods of the Transaction object The Commit( ) method of the Transaction is used to commit the database transaction The Rollback( ) method of the Transaction is used to roll back a database transaction from a pending state

An InvalidOperationException will be raised if Rollback( )

is called after Commit( ) has been called

The isolation level of the transaction can be specified through

an overload of the BeginTransaction( ) method and if it is not specified, the default isolation level ReadCommitted is used

Unlike automatic transactions, manual transactions must be explicitly committed or rolled back using the Commit( ) or

Rollback( ) method If possible, use the NET data provider transaction management exclusively; avoid using other

transaction models, such as the one provided by SQL Server If this is necessary for any reason, Recipe 6.3 discusses using the SQL Server transaction model together with the NET SQL

Server data provider transaction management

The IDbTransaction interface is implemented by NET data providers that access relational databases Applications create

an instance of the class implementing the IDbTransaction

interface rather than creating an instance of the interface

directly Classes that inherit IDbTransaction must implement the inherited members and typically define provider-specific functionality by adding additional members

The SQL NET data provider allows savepoints to be defined

allowing a transaction to be partially rolled back to a point in the transaction other than its beginning The OLE DB NET data provider allows nested transactions to be started within the

parent transaction; the parent transaction cannot commit until

Trang 6

all its nested transactions have committed.

Trang 7

Recipe 6.3 Nesting Manual Transactions with the SQL Server NET Data Provider

Problem

You need to create a nested transaction using the SQL Server NET data provider, but the Begin( ) command that you need

is only available with the OLE DB NET data provider The SQL Server data provider appears to provide no built-in support for nested transactions You want to nest transactions when using it

Solution

Simulate nested transactions with savepoints when using the SQL Server NET data provider, manage and control the lifetime

of the SqlTransaction class, and create the required exception handling

The sample code contains two event handlers:

Form.Load

Sets up the sample by filling a DataTable with the

Categories table from the Northwind sample database The default view of the table is bound to a data grid on the

form

Insert Button.Click

Inserts user-entered data for two Categories records into the Northwind database within a manual transaction A

savepoint is created if the first record insert succeeds If

Trang 8

back to the savepoint and the first record insert is

committed; otherwise, both record inserts are committed

The C# code is shown in Example 6-4

Example 6-4 File:

NestedManualTransactionForm.cs

// Namespaces, variables, and constants

using System;

using System.Configuration;

using System.Windows.Forms;

using System.Data;

using System.Data.SqlClient;

private const String CATEGORIES_TABLE = "Categories";

private DataTable dt;

private SqlDataAdapter da;

//

private void NestedTransactionForm_Load(object sender, System.EventArgs e) {

// Fill the categories table

String sqlText = "SELECT CategoryID, CategoryName, " +

"Description FROM Categories";

da = new SqlDataAdapter(sqlText,

ConfigurationSettings.AppSettings["Sql_ConnectString"]);

dt = new DataTable(CATEGORIES_TABLE);

da.FillSchema(dt, SchemaType.Source);

da.Fill(dt);

// Bind the default view of the table to the grid

dataGrid.DataSource = dt.DefaultView;

Trang 9

private void insertButton_Click(object sender, System.EventArgs e) {

String sqlText = "INSERT " + CATEGORIES_TABLE + " "+

"(CategoryName, Description) VALUES " +

"(@CategoryName, @Description)";

// Create the connection

SqlConnection conn = new SqlConnection(

ConfigurationSettings.AppSettings["Sql_ConnectString"]); // Create the transaction

conn.Open( );

SqlTransaction tran = conn.BeginTransaction( );

// Create command in the transaction with parameters

SqlCommand cmd = new SqlCommand(sqlText, conn, tran);

cmd.Parameters.Add(new SqlParameter("@CategoryName",

SqlDbType.NVarChar, 15));

cmd.Parameters.Add(new SqlParameter("@Description",

SqlDbType.NVarChar, 100));

try

{

// Insert the records into the table

if (categoryName1TextBox.Text.Trim( ).Length == 0)

// If CategoryName is empty, make it null (invalid) cmd.Parameters["@CategoryName"].Value = DBNull.Value; else

cmd.Parameters["@CategoryName"].Value =

categoryName1TextBox.Text;

cmd.Parameters["@Description"].Value =

description1TextBox.Text;

cmd.ExecuteNonQuery( );

}

catch (Exception ex)

{

Trang 10

tran.Rollback( );

MessageBox.Show(ex.Message + Environment.NewLine +

"Transaction rollback (records 1 and 2).");

conn.Close( );

return;

}

tran.Save("SavePoint1");

try

{

// Insert the records into the table

if (categoryName2TextBox.Text.Trim( ).Length == 0)

// If CategoryName is empty, make it null (invalid)

cmd.Parameters["@CategoryName"].Value = DBNull.Value; else

cmd.Parameters["@CategoryName"].Value =

categoryName2TextBox.Text;

cmd.Parameters["@Description"].Value =

description2TextBox.Text;

cmd.ExecuteNonQuery( );

// If okay to here, commit the transaction

tran.Commit( );

MessageBox.Show("Transaction committed (records 1 and 2)."); }

catch (SqlException ex)

{

tran.Rollback("SavePoint1");

tran.Commit( );

MessageBox.Show(ex.Message + Environment.NewLine +

"Transaction commit (record 1)." + Environment.NewLine + "Transaction rollback (record 2).");

}

finally

Trang 11

conn.Close( );

}

// Refresh the data

da.Fill(dt);

}

Discussion

The OLE DB NET data provider's transaction class

OleDbTransaction has a Begin( ) method that is used to

initiate a nested transaction A nested transaction allows part of

a transaction to be rolled back without rolling back the entire transaction An InvalidOperationException is raised if the OLE DB data source does not support nested transactions

The SQL Server NET data provider's transaction class

SqlTransaction does not have a Begin( ) method to initiate a nested transaction Instead, it has a Save( ) method that

creates a savepoint in the transaction that can later be used to roll back a portion of the transactionto the savepoint rather

than rolling back to the start of the transaction The savepoint

is named using the only argument of the Save( ) method An overload of the Rollback( ) method of the SqlTransaction

class accepts an argument that you can use to specify the name

of the savepoint to roll back to

Ngày đăng: 26/03/2019, 17:13

🧩 Sản phẩm bạn có thể quan tâm