.Net中的5種事務總結 ?
.Net 2010-01-29 23:52:28 閱讀 164 評論 0 ? ??字號: 大 中 小 ? 訂閱
1、SQL事務
??? sql事務是使用SQL server自身的事務:在存儲過程中直接使用Begin Tran,Rollback Tran,Commit Tran實現事務:
優點:執行效率最佳
限制:事務上下文僅在數據庫中調用,難以實現復雜的業務邏輯。
Demo:(所有demo,都以SQL Server自帶的Northwind數據的表Region為例)
帶事務的存儲過程
CREATE PROCEDURE dbo.SPTransaction
??? (
??? @UpdateID int,
??? @UpdateValue nchar(50),
??? @InsertID int,
??? @InsertValue nchar(50)
??? )
AS
begin Tran
Update Region? Set where RegionID=@UpdateID
insert into Region Values (@InsertID,@InsertValue)
declare @RegionError int
select @RegionError=@@error
if(@RegionError=0)
COMMIT Tran
else
ROLLBACK Tran
GO
執行帶事務的存儲過程
/**//// <summary>
??????? /// SQL事務:
??????? /// </summary>
??????? public void SQLTran()
??????? {
??????????? SqlConnection conn = new SqlConnection("Da
??????????? SqlCommand cmd = new SqlCommand();
??????????? cmd.CommandText = "SPTransaction";
??????????? cmd.CommandType = CommandType.StoredProcedure;
??????????? cmd.Connection = conn;
??????????? conn.Open();
??????????? SqlParameter[] paras= new SqlParameter[]{
??????????????????????????????????????? new SqlParameter ("@UpdateID",SqlDbType.Int,32),
??????????????????????????????????????? new SqlParameter ("@UpdateValue",SqlDbType .NChar,50),
??????????????????????????????????????? new SqlParameter ("@InsertID",SqlDbType.Int ,32),
??????????????????????????????????????? new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
??????????? paras[0].Value = "2";
??????????? paras[1].Value = "Update Value1";
??????????? paras[2].Value = "6";
??????????? paras[3].Value = "Insert Value1";
??????????? foreach (SqlParameter para in paras )
??????????? {
??????????????? cmd.Parameters.Add(para);
??????????? }
??????????? cmd.ExecuteNonQuery();??
??????? }
2、ADO.net事務
?? Ado.net事務可能是大家一般都用的
?優點:簡單,效率和數據庫事務差不多。
?缺點:事務不能跨數據庫,只能在一個數據庫連接上。如果是兩個數據庫上就不能使用該事務了。
Demo:
ADO.net事務
/**//// <summary>
??????? /// 一般的ADO.net 事務
??????? /// </summary>
??????? public void ADONetTran1()
??????? {
??????????? SqlConnection conn = new SqlConnection("Da
??????????? SqlCommand cmd = new SqlCommand();
??????????? try
??????????? {
??????????????? cmd.CommandText = "Update Region Set where RegionID=@UpdateID";
??????????????? cmd.CommandType = CommandType.Text;
??????????????? cmd.Connection = conn;
??????????????? conn.Open();
??????????????? SqlParameter[] paras = new SqlParameter[]{
??????????????????????????????????????? new SqlParameter ("@UpdateID",SqlDbType.Int,32),
??????????????????????????????????????? new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
??????????????? paras[0].Value = "2";
??????????????? paras[1].Value = "Update Value12";
??????????????? foreach (SqlParameter para in paras)
??????????????? {
??????????????????? cmd.Parameters.Add(para);
??????????????? }
??????????????? //開始事務
??????????????? cmd.Transaction = conn.BeginTransaction();
??????????????? cmd.ExecuteNonQuery();
??????????????? cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
??????????????? cmd.CommandType = CommandType.Text;
??????????????? paras = new SqlParameter[]{
??????????????????????????????????????? new SqlParameter ("@InsertID",SqlDbType.Int ,32),
??????????????????????????????????????? new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
??????????????? paras[0].Value = "7";
??????????????? paras[1].Value = "Insert Value";
??????????????? cmd.Parameters.Clear();
??????????????? foreach (SqlParameter para in paras)
??????????????? {
??????????????????? cmd.Parameters.Add(para);
??????????????? }
???????????????
??????????????? cmd.ExecuteNonQuery();
??????????????? //提交事務
??????????????? cmd.Transaction.Commit();
??????????? }
??????????? catch
??????????? {
??????????????? //回滾事務
??????????????? cmd.Transaction.Rollback();
??????????????? throw;
??????????? }
??????????? finally
??????????? {
??????????????? conn.Close();
??????????? }
??????? }
3、TransactionScope事務
? TransactionScope事務類,它可以使代碼塊成為事務性代碼。并自動提升為分布式事務
?優點:實現簡單,同時能夠自動提升為分布式事務
Demo:
TransactionScope事務
?/**//// <summary>
??????? /// TransactionScope事務:可自動提升事務為完全分布式事務的輕型(本地)事務。
??????? /// 使用時要保證MSDTC服務(控制分布事務)是開啟的可以使用:net start msdtc命令開啟服務;
??????? /// </summary>
??????? public void ADONetTran2()
??????? {
???????????? SqlConnection conn = new SqlConnection("Da
???????????? SqlCommand cmd = new SqlCommand();
??????????? try
??????????? {
?????????????
??????????????? using (System.Transactions.TransactionScope ts = new TransactionScope())
??????????????? {
???????????????????
??????????????????? cmd.CommandText = "Update Region Set where RegionID=@UpdateID";
??????????????????? cmd.CommandType = CommandType.Text;
??????????????????? cmd.Connection = conn;
??????????????????? conn.Open();
??????????????????? SqlParameter[] paras = new SqlParameter[]{
??????????????????????????????????????? new SqlParameter ("@UpdateID",SqlDbType.Int,32),
??????????????????????????????????????? new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
??????????????????? paras[0].Value = "2";
??????????????????? paras[1].Value = "Update Value12";
??????????????????? foreach (SqlParameter para in paras)
??????????????????? {
??????????????????????? cmd.Parameters.Add(para);
??????????????????? }
??????????????????? cmd.ExecuteNonQuery();
??????????????????? cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
??????????????????? cmd.CommandType = CommandType.Text;
??????????????????? paras = new SqlParameter[]{
??????????????????????????????????????? new SqlParameter ("@InsertID",SqlDbType.Int ,32),
??????????????????????????????????????? new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
??????????????????? paras[0].Value = "8";
??????????????????? paras[1].Value = "Insert Value";
??????????????????? cmd.Parameters.Clear();
??????????????????? foreach (SqlParameter para in paras)
??????????????????? {
??????????????????????? cmd.Parameters.Add(para);
??????????????????? }
??????????????????? cmd.ExecuteNonQuery();
??????????????????? //提交事務
??????????????????? ts.Complete();????????????? //提交事務之前conn不能關閉的(Not conn.Close()),否則報錯
??????????????? }
??????????? }
??????????? catch
??????????? {
??????????????? throw;
??????????? }
??????????? finally
??????????? {
??????????????? conn.Close();
??????????? }
??????? }
4、COM+事務
? 在分布式應用程序中,往往要同時操作多個數據庫,使用數據庫事務就不能滿足業務的要求了。在COM+中,提供完整的事務處理服務。很方便處理多個數據庫上的事務。
例一:
COM+事務
/**//// <summary>
??????? /// COM+事務
??????? /// </summary>
??????? public void ComTran()
??????? {
??????????? SqlConnection conn = new SqlConnection("Da
??????????? SqlCommand cmd = new SqlCommand();
??????????? ServiceConfig sc = new ServiceConfig();
??????????? //指定事務類型
??????????? sc.Transaction = TransactionOption.Required;
??????????? //設置啟動跟蹤
??????????? sc.TrackingEnabled = true;
??????????? //創建一個上下文,該上下文的配置由作為 cfg 參數傳遞的 ServiceConfig 對象來指定。
??????????? //隨后,客戶端和服務器端的策略均被觸發,如同發生了一個方法調用。
??????????? //接著,新的上下文被推至上下文堆棧,成為當前上下文
??????????? ServiceDomain.Enter(sc);
??????????? try
??????????? {
??????????????????? cmd.CommandText = "Update Region Set where RegionID=@UpdateID";
??????????????????? cmd.CommandType = CommandType.Text;
??????????????????? cmd.Connection = conn;
??????????????????? conn.Open();
??????????????????? SqlParameter[] paras = new SqlParameter[]{
??????????????????????????????????????? new SqlParameter ("@UpdateID",SqlDbType.Int,32),
??????????????????????????????????????? new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
??????????????????? paras[0].Value = "2";
??????????????????? paras[1].Value = "Update Value22";
??????????????????? foreach (SqlParameter para in paras)
??????????????????? {
??????????????????????? cmd.Parameters.Add(para);
??????????????????? }
??????????????????? cmd.ExecuteNonQuery();
??????????????????? cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
??????????????????? cmd.CommandType = CommandType.Text;
??????????????????? paras = new SqlParameter[]{
??????????????????????????????????????? new SqlParameter ("@InsertID",SqlDbType.Int ,32),
??????????????????????????????????????? new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
??????????????????? paras[0].Value = "9";
??????????????????? paras[1].Value = "Insert Value";
??????????????????? cmd.Parameters.Clear();
??????????????????? foreach (SqlParameter para in paras)
??????????????????? {
??????????????????????? cmd.Parameters.Add(para);
??????????????????? }
??????????????????? cmd.ExecuteNonQuery();
??????????????????? //提交事務
??????????????????? ContextUtil.SetComplete();
??????????? }
??????????? catch
??????????? {
??????????????? //回滾事務
??????????????? ContextUtil.SetAbort();
??????????????? throw;
??????????? }
??????????? finally
??????????? {
??????????????? conn.Close();
??????????????? //觸發服務器端的策略,隨后觸發客戶端的策略,如同一個方法調用正在返回。
??????????????? //然后,當前上下文被彈出上下文堆棧,調用 Enter 時正在運行的上下文成為當前的上下文。
??????????????? ServiceDomain.Leave();
??????????? }
需要特別補充的是:
如果你使用的是分布事務(TransactionScope事務和COM+事務),在默認情況下你是要重新配置安裝SQL Server數據庫服務器和訪問數據庫的客戶端的.(如果沒有配置運行會出現以下錯誤:該伙伴事務管理器已經禁止了它對遠程/網絡事務的支持。 (異常來自 HRESULT:0x8004D025)
)下面是MSDN上關于配置分布式事務的一段原話:
配置分布式事務
要啟用分布式事務,可能需要通過網絡啟用 MS DTC,以便在使用應用了最新的 Service Pack 的較新操作系統(例如 Windows XP 或 Windows 2003)時使用分布式事務。如果啟用了 Windows 防火墻(Windows XP Service Pack 2 的默認設置),必須允許 MS DTC 服務使用網絡或打開 MS DTC 端口。
實際怎么配置呢,經過我的實際使用:大致如下:打開'控制面板'->'管理工具'->'組件服務',點開'組件服務'->'計算機'->'我的電腦',在'我的電腦'上右擊屬性,點'MSDTC',然后點'安全性配置'。作為數據庫的服務器的配置如下:
而訪問數據庫的客戶端的配置和服務器端的稍有些差別:
在設置完上面的還有使防火墻MS DTC 服務使用網絡或打開 MS DTC 端口:運行netsh firewall set allowedprogram %windir%\system32\msdtc.exe MSDTC enable命令就可以了
ASP.NET事務可以說是在.NET平臺上事務實現方式最簡單的一種,你僅僅需要一行代碼即可。在aspx的頁面聲明中加一個額外的屬性,即事務屬性 Transaction="Required" ,它有如下的值:Disabled(默認)、NotSupported、Supported、Required和RequiresNew,這些設置和COM+及企業級服務中的設置一樣,典型的一個例子是如果你想在頁面上下文中運行事務,那么要將其設置為Required。如果頁面中包含有用戶控件,那么這些控件也會包含到事務中,事務會存在于頁面的每個地方。
頁面聲明Transaction="Required":
<%@ Page Transaction="Required" ?Language="C#" AutoEventWireup="true"
CodeBehind="WebForm3.aspx.cs" Inherits="WebApplication4.WebForm3" %>
頁面引用:using System.EnterpriseServices;。
然后,數據操作代碼:
protected void Button1_Click(object sender, EventArgs e)
{
??? try
??? {
??????? Work1();
??????? Work2();
??????? ContextUtil.SetComplete();?? // 提交事務
??? }
??? catch (System.Exception except)
??????? ContextUtil.SetAbort();????? // 撤銷事務
??????? Response.Write(except.Message);
??? }?
}?
private void Work1()
{
??? string conString = "da
????? password=";
??? SqlConnection myConnection = new SqlConnection(conString);
??? string strSql = "Insert Into P_Category(CategoryId,Name)values('1',
????? 'test1')";
??? SqlCommand myCommand = new SqlCommand(strSql, myConnection);
??? myConnection.Open();
??? int rows = myCommand.ExecuteNonQuery();
??? myConnection.Close();
}
private void Work2()
{
??? string conString = "da
????? password=";
??? SqlConnection myConnection = new SqlConnection(conString);
??? string strSql = "Insert Into P_Category(CategoryId,Name)values('2',
????? 'test2')";
??? SqlCommand myCommand = new SqlCommand(strSql, myConnection);
??? myConnection.Open();
??? int rows = myCommand.ExecuteNonQuery();
??? myConnection.Close();
}
ContextUtil是用于獲取 COM+ 上下文信息的首選類。由于此類的成員全部為static,因此在使用其成員之前不需要對此類進行實例化。
ASP.NET頁面事務的優勢和限制如下。
??? l限制:頁面的所有代碼都是同一個事務,這樣的事務可能會很大,而也許我們需要的是分開的、小的事務實現在Web層。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
