System.Data.SqlClient namespace包括了SqlTransaction类。此类包括了两个属性:
◆Connection:指示同事务处理相关联的SqlConnection对象;
◆IsolationLevel:定义事务处理的IsolationLevel。
属性IsolationLevel是包括如下成员的枚举对象:
◆Chaos:从高度独立的事务处理中出现的pending changes不能被覆盖;
◆ReadCommitted:当数据需要被非恶意读取时,采用共享锁定(shared locks),但数据仍然可以在事务处理结束时被更新,这造成了非重复性的数据读取(nonrepeatable reads)或phantom data的产生;
◆ReadUncommitted:恶意读取数据是可能发生的,这表示没有使用共享锁定(shared locks),并且没有实现独占锁定(exclusive locks);
◆RepeatableRead:锁定查询中所用到的所有数据,由此避免其他用户对数据进行更新。在phantom rows仍然可用的状态下,这可以避免非重复性的数据读取(nonrepeatable reads);
◆Serialisable:在DataSet中进行范围锁定,由此防止其他用户在事务处理结束之前更新数据或在数据库中插入行;
◆IsolationLevel定义锁定记录的级别,但这一概念不在本文论述范围之内。对象SqlTransaction也提供了类似的方法。你可以使用以下方法来进行事务处理;
◆Commit:提交数据库事务处理;
◆Rollback:从未决状态(pending state)反转(roll back)事务处理。事务处理一旦被提交后即不能执行此操作;
◆Save:在事务处理中创建savepoint可以对事务处理的一部分进行反转,并且指定savepoint名称。
例子:
CREATE PROCEDURE up_purchaseItem (
@customerId as int,
@itemId int,
@itemqty int)
AS
DECLARE @orderid int
BEGIN TRANSACTION
-- Update the inventory based on purchase
UPDATE inventory
SET qtyinstock = qtyinstock - @itemqty
WHERE inventory.productid = @itemid;
IF @@Error != 0 GOTO ERROR_HANDLER
-- Insert the order into the database
INSERT INTO orders
VALUES (@customerId, @itemId, @itemqty, getdate());
IF @@Error != 0 GOTO ERROR_HANDLER
SET @orderid = @@IDENTITY
COMMIT TRANSACTION
RETURN @orderid
ERROR_HANDLER:
ROLLBACK TRANSACTION
SET NOCOUNT OFF
RETURN 0
GO
ADO.NET事務
創建一個ADO.NET事務是很簡單的,僅僅是標準代碼的一個小的擴展。只要你知道如何使用ADO.NET來訪問數據庫,那就差不多知道了。區別僅僅是你需要把代碼放到一個事務上下文中。
還是原來的ADO.NET類庫引用,在實現事務的類裏面引入System.Data和System.Data.SqlClient類庫,為了執行一個事 務,你需要創建一個SqlTransation對象,可以調用你的SqlConnection對象BeginTransation()方法來創建它,一旦 你把SqlTransation對象存為本地變數,你就可以把它賦給你的SqlCommand對象的事務屬性,或者把它作為構造器的一個參數來創建 SqlCommand。在執行SqlCommand動作之前,你必須調用BeginTransaction()方法,然後賦給SqlCommand事務屬 性。
一單事務開始了,你就可以執行任何次數的SqlCommand動作,只要它是屬於同一個事務和連接。最後你可以調用SqlTransation的Commit()方法來提交事務。
ADO.NET事務實際上是把事務上下文傳遞到數據庫層,如果事務中發生一個錯誤,數據庫會自動回滾。在你的錯誤處理代碼中,每次調用Rollback ()方法之前檢查事務對像是否存在是一種良好的習慣。這樣的一個例子是當一個死鎖發生的同時,數據庫正在執行自動回滾。
優勢:
◆ 簡單性
◆ 和數據庫事務差不多的快
◆ 事務可以跨越多個數據庫訪問
◆ 獨立於數據庫,不同數據庫的專有代碼被隱藏了
限制:
事務執行在數據庫連接層上,所以你需要在事務過程中手動的維護一個連接
例子:
public int purchaseitem(int customerId, int itemId, int itemQty)
{
SqlConnection con = null;
SqlTransaction tx = null;
int orderId = 0;
try
{
con = new SqlConnection("Data Source=localhost; user
Id=sa;password=;Initial Catalog=trans_db;");
con.Open();
tx = con.BeginTransaction(IsolationLevel.Serializable);
String updatesqltext = "UPDATE inventory SET qtyinstock
= qtyinstock - " + itemQty.ToString()
+ " WHERE inventory.productid = " + itemId.ToString();
SqlCommand cmd = new SqlCommand(updatesqltext, con, tx);
cmd.ExecuteNonQuery();
// String is 2 SQL statements: the first is the insert,
the second selects the identity column
String insertsqltext = "INSERT INTO orders VALUES
(" + customerId.ToString() + "," + itemId.ToString()
+ "," + itemQty.ToString() + " , getdate() ); SELECT @@IDENTITY";
cmd.CommandText = insertsqltext;
// Retrieve the order id from the identity column
orderId = Convert.ToInt32(cmd.ExecuteScalar());
cmd.Dispose();
tx.Commit();
}
catch (SqlException sqlex)
{
// Specific catch for deadlock
if (sqlex.Number != 1205)
{
tx.Rollback();
}
orderId = 0;
throw(sqlex);
}
catch (Exception ex)
{
tx.Rollback();
orderId = 0;
throw (ex);
}
finally
{
tx.Dispose();
con.Close();
}
}
ASP.NET事務
ASP.NET事務可以說是在.Net平臺上事務實現方式中最簡單的一種,你僅僅需要加一行代碼。在ASPX的頁面聲明中加一個額外的屬性,即是事務屬 性,它可以有 如下的值:Disabled (缺省), NotSupported, Supported, Required 和 RequiresNew,這些設置和COM+以及企業級服務中的設置一樣,典型地如果你想在頁面上下文中運行事務,那麼要設置為Required。如果頁 面中包含有用戶控件,那麼這些控件也會包含到事務中,事務會存在於頁面的每個地方。
優勢:
◆ 實現簡單,不需要額外的編碼
限制:
◆ 頁面的所有代碼都是同一個事務,這樣的事務可能會很大,而也許我們需要的是分開的、小的事務
◆ 事務實在Web層
例子:
ASPX page
<%@ Page Transaction="Required" language="c#" Codebehind="ASPNET_Transaction.aspx.cs"
Inherits="TransTest.ASPNET_Transaction" AutoEventWireup="false"%>