小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

各種事務(wù)處理方式大比拼

 kittywei 2012-08-23

事務(wù)是一組組合成邏輯工作單元的數(shù)據(jù)庫操作,在系統(tǒng)執(zhí)行過程中可能會(huì)出錯(cuò),但事務(wù)將控制和維護(hù)每個(gè)數(shù)據(jù)庫的一致性和完整性。事務(wù)處理的主要特征是,任務(wù)要么全部完成,要么都不完成。在寫入一些記錄時(shí),要么寫入所有記錄,要么什么都不寫入。如果在寫入一個(gè)記錄時(shí)出現(xiàn)了一個(gè)失敗,那么在事務(wù)處理中已寫入的其他數(shù)據(jù)就會(huì)回滾。事務(wù)可能由很多單個(gè)任務(wù)構(gòu)成。

簡單事務(wù)的一個(gè)常見例子:把錢從A賬戶轉(zhuǎn)到B賬戶,這涉及兩項(xiàng)任務(wù),即從A賬戶把錢取出來;把錢存入B賬戶。兩項(xiàng)任務(wù)要么同時(shí)成功,要么一起失敗,給予回滾,以便保持賬戶的狀態(tài)和原來相同。否則,在執(zhí)行某一個(gè)操作的時(shí)候可能會(huì)因?yàn)橥k?、網(wǎng)絡(luò)中斷等原因而出現(xiàn)故障,所以有可能更新了一個(gè)表中的行,但沒有更新相關(guān)表中的行。如果數(shù)據(jù)庫支持事務(wù),則可以將數(shù)據(jù)庫操作組成一個(gè)事務(wù),以防止因這些事件而使數(shù)據(jù)庫出現(xiàn)不一致。

事務(wù)的ACID屬性如下。

原子性(Atomicity):事務(wù)的所有操作是原子工作單元;對(duì)于其數(shù)據(jù)修改,要么全都執(zhí)行,要么全都不執(zhí)行。原子性消除了系統(tǒng)處理操作子集的可能性。

一致性(Consistency):數(shù)據(jù)從一種正確狀態(tài)轉(zhuǎn)換到另一種正確狀態(tài)。事務(wù)在完成時(shí),必須使所有的數(shù)據(jù)都保持一致。在相關(guān)數(shù)據(jù)庫中,所有規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持所有數(shù)據(jù)的完整性。當(dāng)事務(wù)結(jié)束時(shí),所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)都必須是正確的。在存款取款的例子中,邏輯規(guī)則是,錢是不能憑空產(chǎn)生或銷毀的,對(duì)于每個(gè)(收支)條目必須有一個(gè)相應(yīng)的抵衡條目產(chǎn)生,以保證賬戶是平的。

隔離性(Isolation):由并發(fā)事務(wù)所作的修改必須與任何其他并發(fā)事務(wù)所作的修改隔離。查看數(shù)據(jù)時(shí)數(shù)據(jù)所處的狀態(tài),要么是事務(wù)修改它之前的狀態(tài),要么是事務(wù)修改它之后的狀態(tài)。簡單的理解就是,防止多個(gè)并發(fā)更新彼此干擾。事務(wù)在操作數(shù)據(jù)時(shí)與其他事務(wù)操作隔離。隔離性一般是通過加鎖的機(jī)制來實(shí)現(xiàn)的。

持久性(Durability):事務(wù)完成之后,它對(duì)于系統(tǒng)的影響是永久性的。已提交的更改即使在發(fā)生故障時(shí)也依然存在。

對(duì)于事務(wù)的開發(fā),.NET平臺(tái)也為我們提供了幾種非常簡單方便的事務(wù)機(jī)制。無論是在功能上還是性能上都提供了優(yōu)秀的企業(yè)級(jí)事務(wù)支持。

.NET開發(fā)者可以使用以下5種事務(wù)機(jī)制:

SQL和存儲(chǔ)過程級(jí)別的事務(wù)。

ADO.NET級(jí)別的事務(wù)。

ASP.NET頁面級(jí)別的事務(wù)。

企業(yè)級(jí)服務(wù)COM+事務(wù)。

System.Transactions 事務(wù)處理。

5種事務(wù)機(jī)制有著各自的優(yōu)勢(shì)和劣勢(shì),分別表現(xiàn)在性能、代碼數(shù)量和部署設(shè)置等方面。開發(fā)人員可以根據(jù)項(xiàng)目的實(shí)際情況選擇相應(yīng)的事務(wù)機(jī)制。下面就開始分別說明日常開發(fā)中5種事務(wù)的具體使用。

 

一、sql和存儲(chǔ)過程級(jí)別事務(wù)

 

 

數(shù)據(jù)庫事務(wù)是其他事務(wù)模型的基礎(chǔ),當(dāng)一個(gè)事務(wù)創(chuàng)建時(shí)不同數(shù)據(jù)庫系統(tǒng)都有自己的規(guī)則。SQL Server默認(rèn)在自動(dòng)提交的模式下工作,每個(gè)語句執(zhí)行完后都會(huì)立即提交;與此對(duì)照的是Oracle需要你包含一個(gè)提交語句。但是當(dāng)一個(gè)語句通過OLE DB執(zhí)行時(shí),它執(zhí)行完后一個(gè)提交動(dòng)作會(huì)被附加上去。例如:

DECLARE @TranName VARCHAR(20);

SELECT @TranName = 'MyTransaction';

 

BEGIN TRANSACTION @TranName;

GO

USE AdventureWorks;

GO

DELETE FROM AdventureWorks.HumanResources.JobCandidate

    WHERE JobCandidateID = 13;

 

GO

 

 

COMMIT TRANSACTION MyTransaction;

GO

或者:

CREATE PROCEDURE Tran1 

as 

begin tran 

set xact_abort on

Insert Into P_Category(CategoryId,Name)values('1','test1') 

Insert Into P_Category(CategoryId,Name)values('2','test2') 

commit tran 

GO

set xact_abort on表示遇到錯(cuò)誤立即回滾。

當(dāng)然你也可以這么寫:

CREATE PROCEDURE tran1

as

begin tran

Insert Into P_Category(CategoryId,Name)values('1','test1') 

if(@@error<>0)

 rollback tran

else

 begin

 Insert Into P_Category(CategoryId,Name)values('2','test2')

 if(@@error<>0)

   rollback tran

 else

   commit tran

 end

GO

數(shù)據(jù)庫級(jí)別事務(wù)有它的優(yōu)勢(shì)和限制。

優(yōu)勢(shì):

所有的事務(wù)邏輯包含在一個(gè)單獨(dú)的調(diào)用中。

擁有運(yùn)行一個(gè)事務(wù)的最佳性能。

獨(dú)立于應(yīng)用程序。

限制:

事務(wù)上下文僅存在于數(shù)據(jù)庫調(diào)用中。

數(shù)據(jù)庫代碼與數(shù)據(jù)庫系統(tǒng)有關(guān)。

 

二、ado.net級(jí)別的事務(wù)

 

現(xiàn)在我們對(duì)事務(wù)的概念和原理都有所了解了,并且作為已經(jīng)有一些基礎(chǔ)的C#開發(fā)者,我們已經(jīng)熟知編寫數(shù)據(jù)庫交互程序的一些要點(diǎn),即:

1)使用SqlConnection類的對(duì)象的Open()方法建立與數(shù)據(jù)庫服務(wù)器的連接。

2)然后將該連接賦給SqlCommand對(duì)象的Connection屬性。

3)將欲執(zhí)行的SQL語句賦給SqlCommandCommandText屬性。

4)通過SqlCommand對(duì)象進(jìn)行數(shù)據(jù)庫操作。

創(chuàng)建一個(gè)ADO.NET事務(wù)是很簡單的,需要定義一個(gè)SqlTransaction類型的對(duì)象。SqlConnection OleDbConnection對(duì)象都有一個(gè) BeginTransaction 方法,它可以返回 SqlTransaction 或者OleDbTransaction 對(duì)象。然后賦給SqlCommand對(duì)象的Transcation屬性,即實(shí)現(xiàn)了二者的關(guān)聯(lián)。為了使事務(wù)處理可以成功完成,必須調(diào)用SqlTransaction對(duì)象的Commit()方法。如果有錯(cuò)誤,則必須調(diào)用Rollback()方法撤銷所有的操作。

代碼示例:

基于以上認(rèn)識(shí),下面我們就開始動(dòng)手寫一個(gè)基于ADO.NET的事務(wù)處理程序。

                                            (示例位置:光盤\code\ch05\04\Web\WebForm2

string conString = "data source=127.0.0.1;database=codematic;user id=sa;

password=";

SqlConnection myConnection = new SqlConnection(conString);

myConnection.Open();

 

//啟動(dòng)一個(gè)事務(wù)

SqlTransaction myTrans = myConnection.BeginTransaction();

 

//為事務(wù)創(chuàng)建一個(gè)命令

SqlCommand myCommand = new SqlCommand();

myCommand.Connection = myConnection;

myCommand.Transaction = myTrans;

try

{

    myCommand.CommandText = "update P_Product set Name='電腦2' where Id=52";

    myCommand.ExecuteNonQuery();

    myCommand.CommandText = "update P_Product set Name='電腦3' where Id=53";

    myCommand.ExecuteNonQuery();

    myTrans.Commit();//提交

    Response.Write("兩條數(shù)據(jù)更新成功");

}

catch (Exception ex)

{

    myTrans.Rollback();//遇到錯(cuò)誤,回滾

    Response.Write(ex.ToString());              

}

finally

{

    myConnection.Close();

}

ADO.NET事務(wù)的優(yōu)勢(shì)和限制如下。

優(yōu)勢(shì):

簡單。

和數(shù)據(jù)庫事務(wù)差不多快。

事務(wù)可以跨越多個(gè)數(shù)據(jù)庫訪問。

獨(dú)立于數(shù)據(jù)庫,不同數(shù)據(jù)庫的專有代碼被隱藏了。

限制:事務(wù)執(zhí)行在數(shù)據(jù)庫連接層上,所以需要在執(zhí)行事務(wù)的過程中手動(dòng)地維護(hù)一個(gè)連接。

注 意

所有命令都必須關(guān)聯(lián)在同一個(gè)連接實(shí)例上,ADO.NET事務(wù)處理不支持跨多個(gè)連接的事務(wù)處理。

 

三、asp.net 頁面級(jí)別事務(wù)處理

ASP.NET事務(wù)可以說是在.NET平臺(tái)上事務(wù)實(shí)現(xiàn)方式最簡單的一種,你僅僅需要一行代碼即可。在aspx的頁面聲明中加一個(gè)額外的屬性,即事務(wù)屬性Transaction="Required",它有如下的值:Disabled(默認(rèn))、NotSupportedSupported、RequiredRequiresNew,這些設(shè)置和COM+及企業(yè)級(jí)服務(wù)中的設(shè)置一樣,典型的一個(gè)例子是如果你想在頁面上下文中運(yùn)行事務(wù),那么要將其設(shè)置為Required。如果頁面中包含有用戶控件,那么這些控件也會(huì)包含到事務(wù)中,事務(wù)會(huì)存在于頁面的每個(gè)地方。

        

代碼示例:

頁面聲明Transaction="Required"

<%@ Page Transaction="Required"  Language="C#" AutoEventWireup="true"

CodeBehind="WebForm3.aspx.cs" Inherits="WebApplication4.WebForm3" %>

頁面引用:using System.EnterpriseServices;。

然后,數(shù)據(jù)操作代碼:

protected void Button1_Click(object sender, EventArgs e)

{

    try

    {

        Work1();

        Work2();

        ContextUtil.SetComplete();   //提交事務(wù)

    }

    catch (System.Exception except)

    {

        ContextUtil.SetAbort();      //撤銷事務(wù)

        Response.Write(except.Message);

    } 

private void Work1()

{

    string conString = "data source=127.0.0.1;database=codematic;user id=sa;

      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 = "data source=127.0.0.1;database=codematic;user id=sa;

      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,因此在使用其成員之前不需要對(duì)此類進(jìn)行實(shí)例化。

ASP.NET頁面事務(wù)的優(yōu)勢(shì)和限制如下。

優(yōu)勢(shì):實(shí)現(xiàn)簡單,不需要額外的編碼。

    l限制:頁面的所有代碼都是同一個(gè)事務(wù),這樣的事務(wù)可能會(huì)很大,而也許我們需要的是分開的、小的事務(wù)實(shí)現(xiàn)在Web層。

 

   四、企業(yè)級(jí)事務(wù)處理COM+

 

NET Framework 依靠 MTS/COM+ 服務(wù)來支持自動(dòng)事務(wù)處理。COM+ 使用 Microsoft Distributed Transaction CoordinatorDTC)作為事務(wù)管理器和事務(wù)協(xié)調(diào)器在分布式環(huán)境中運(yùn)行事務(wù)。這樣可使 .NET 應(yīng)用程序運(yùn)行跨多個(gè)資源結(jié)合不同操作(例如將定單插入SQL Server 數(shù)據(jù)庫、將消息寫入 Microsoft 消息隊(duì)列(MSMQ)隊(duì)列,以及從 Oracle 數(shù)據(jù)庫檢索數(shù)據(jù))的事務(wù)。

要實(shí)現(xiàn)COM+事務(wù)處理的類則必須繼承System.EnterpriseServices.ServicedComponent這些類需要是公共的,并且需要提供一個(gè)公共的默認(rèn)的構(gòu)造器。其實(shí)Web Service就是繼承ServicedComponent,所以Web Service也支持COM+事務(wù)。要在類定義之前加屬性[Transaction(TransactionOption.Required)]。類里面的每個(gè)方法都會(huì)運(yùn)行在一個(gè)事務(wù)中。

定義一個(gè)COM+事務(wù)處理的類:

首先引用:using System.EnterpriseServices;。

然后,繼承ServicedComponent。

[Transaction(TransactionOption.Required)]

public class OrderData : ServicedComponent

{

}

TransactionOption枚舉類型支持5個(gè)值:Disabled、NotSupported、RequiredRequiresNewSupported,如表5-3所示。

5-3 TransactionOption枚舉類型支持5個(gè)值

   

Disabled

忽略當(dāng)前上下文中的任何事務(wù)

NotSupported

使用非受控事務(wù)在上下文中創(chuàng)建組件

Required

如果事務(wù)存在則共享事務(wù),并且如有必要?jiǎng)t創(chuàng)建新事務(wù)

RequiresNew

使用新事務(wù)創(chuàng)建組件,而與當(dāng)前上下文的狀態(tài)無關(guān)

Supported

如果事務(wù)存在,則共享該事務(wù)

一般來說COM+中的組件需要Required Supported。當(dāng)組件用于記錄或查賬時(shí)RequiresNew 很有用,因?yàn)榻M件應(yīng)該與活動(dòng)中其他事務(wù)處理的提交或回滾隔離開來。

派生類可以重載基類的任意屬性。如OrderData選用Required,派生類仍然可以重載并指定RequiresNew或其他值。

COM+事務(wù)有手動(dòng)處理和自動(dòng)處理兩種方式,自動(dòng)處理就是在所需要自動(dòng)處理的方法前加上[AutoComplete],根據(jù)方法的正?;驋伋霎惓Q定提交或回滾。手動(dòng)處理就是調(diào)用ContextUtil類中的EnableCommit、SetCompleteSetAbort方法。

實(shí)現(xiàn)步驟如下。

1.給程序添加強(qiáng)名

1)創(chuàng)建一對(duì)密鑰

用來創(chuàng)建密鑰的工具是稱為sn.exe的共享工具。通常通過命令提示運(yùn)行它,該工具可執(zhí)行各種任務(wù)以生成并提取密鑰。我們需要用以下方式來運(yùn)行sn.exe

sn –k c:\key.snk

其中key.snk 代表將保存密鑰的文件的名稱。它的名稱可以是任意的,不過習(xí)慣上帶有.snk后綴名。

2)簽名

這個(gè)文件必須在AssemblyKeyFile屬性中引用,簽名通常是在編譯時(shí)進(jìn)行的。簽名時(shí),用戶可利用C#屬性通知編譯器應(yīng)該使用正確的密鑰文件對(duì)DLL進(jìn)行簽名。要做到這一點(diǎn)用戶需要打開工程中的AssemblyInfo.cs文件并進(jìn)行修改。

[assembly:AssemblyKeyFile(“..\\..\\key.snk)]

 

注 意

key.snk文件和項(xiàng)目文件在同一個(gè)文件夾內(nèi)。

2.手動(dòng)事務(wù)處理

創(chuàng)建一個(gè)項(xiàng)目用以實(shí)現(xiàn)事務(wù)處理的業(yè)務(wù)類ClassTran。

代碼示例:

                                     (示例位置:光盤\code\ch05\04\ClassTran\OrderData1

using System;

using System.Data.SqlClient;

using System.EnterpriseServices; //企業(yè)級(jí)服務(wù)COM+事務(wù)

namespace ClassTran

{

    [Transaction(TransactionOption.Required)]

    public class OrderData1 : ServicedComponent

    {

        //手動(dòng)事務(wù)

        public string WorkTran()

        {

            try

            {

                ContextUtil.EnableCommit();

                Work1();

                Work2();

                ContextUtil.SetComplete();

                return "成功!";

            }

            catch (Exception ex)

            {

                ContextUtil.SetAbort();

                return "失敗!";

            }

        }

        private void Work1()

        {

            string conString = "data source=127.0.0.1;database=codematic;

               user id=sa;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 = "data source=127.0.0.1;database=codematic;

               user id=sa;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();

        }

    }

}

3.自動(dòng)事務(wù)處理

代碼示例:

在方法之前增加屬性[AutoComplete(true)],這樣如果方法執(zhí)行時(shí)沒有異常就默認(rèn)提交,如果有異常則這個(gè)方法就會(huì)回滾。

                                    (示例位置:光盤\code\ch05\04\ClassTran\OrderData2

using System;

using System.Data.SqlClient;

using System.EnterpriseServices;//企業(yè)級(jí)服務(wù)COM+事務(wù)

namespace ClassTran

{

    [Transaction(TransactionOption.Required)]

    public class OrderData2 : ServicedComponent

    {

        //自動(dòng)事務(wù)

        [AutoComplete(true)]

        public string WorkTran()

        {

            string msg = "";

            string conString = "data source=127.0.0.1;database=codematic;

               user id=sa;password=";

            SqlConnection myConnection = new SqlConnection(conString);

            myConnection.Open();                                   

            SqlCommand myCommand = new SqlCommand();

            myCommand.Connection = myConnection;           

            try

            {

                myCommand.CommandText = "update P_Product set Name='電腦2'

                    where Id=52";

                myCommand.ExecuteNonQuery();

                myCommand.CommandText = "update P_Product set Name='電腦3'

                where Id=53";

                myCommand.ExecuteNonQuery();

                msg ="成功!";

            }

            catch (Exception ex)

            {

                msg = "失敗:"+ex.Message;              

            }

            finally

            {

                myConnection.Close();

            }

            return msg;

        }

    }

}

4.事務(wù)方法調(diào)用

代碼示例:

                                      (示例位置:光盤\code\ch05\04\Web\WebForm4.aspx

protected void Button1_Click(object sender, EventArgs e)

{

    ClassTran.OrderData1 od1 = new ClassTran.OrderData1();

    od1.WorkTran();

}

protected void Button2_Click(object sender, EventArgs e)

{

    ClassTran.OrderData2 od2 = new ClassTran.OrderData2();

    od2.WorkTran();

}

在需要事務(wù)跨 MSMQ 和其他可識(shí)別事務(wù)的資源(例如SQL Server 數(shù)據(jù)庫)運(yùn)行的系統(tǒng)中,只能使用 DTC COM+ 事務(wù),除此之外沒有其他選擇。DTC 協(xié)調(diào)參與分布式事務(wù)的所有資源管理器,也管理與事務(wù)相關(guān)的操作。

企業(yè)級(jí)服務(wù)COM+事務(wù)的前提及優(yōu)缺點(diǎn)如下。

前提:

需要強(qiáng)名字。

使用事務(wù)的對(duì)象需要繼承ServicedComponent

優(yōu)勢(shì):

執(zhí)行分布式事務(wù),多個(gè)對(duì)象可以輕松地運(yùn)行在同一個(gè)事務(wù)處理中,事務(wù)處理還可以自動(dòng)登記。

獲得COM+服務(wù),諸如對(duì)象構(gòu)建和對(duì)象池等。

缺點(diǎn):

由于存在 DTC COM 互操作性開銷,導(dǎo)致性能降低。

COM+ 1.0要求每個(gè)事務(wù)的隔離級(jí)別都設(shè)置為Serializable

使用Enterprise Services的事務(wù)總是線程安全的, 也就是說你無法讓多個(gè)線程參與到同一個(gè)事務(wù)中。

  

          五、System.Transaction

 

.NET Framework 2.0中增加了System.Transactions,這是一種新的命名空間,完全專注于控制事務(wù)性行為。引入了執(zhí)行事務(wù)性工作的更簡單方法及一些新的性能優(yōu)化。System.Transactions提供了一個(gè)“輕量級(jí)”的、易于使用的Transaction框架。

在上節(jié)中,要實(shí)現(xiàn)Transaction需要利用EnterpriseServices,讓組件從ServiceComponent繼承下來。而通過System.Transactions,則只要簡單的幾行代碼,不需要繼承,不需要Attribute標(biāo)記。用戶根本不需要考慮是簡單事務(wù)還是分布式事務(wù)。新模型會(huì)自動(dòng)根據(jù)事務(wù)中涉及的對(duì)象資源判斷使用何種事務(wù)管理器。簡而言之,對(duì)于任何的事務(wù),用戶只要使用同一種方法進(jìn)行處理即可。

下面介紹System.Transactions的幾種用法。

首先要引用:using System.Transactions;

其次,將事務(wù)操作代碼放在TransactionScope中執(zhí)行。如:

using (TransactionScope ts = new TransactionScope())

{

    //事務(wù)操作代碼

    ts.Complete();

}

代碼示例:

這是最簡單,也是最常見的用法。創(chuàng)建了新的 TransactionScope 對(duì)象后,即開始創(chuàng)建事務(wù)范圍。如代碼示例所示,建議使用 using 語句創(chuàng)建范圍。位于 using 塊內(nèi)的所有操作將成為一個(gè)事務(wù)的一部分,因?yàn)樗鼈児蚕砥渌x的事務(wù)執(zhí)行上下文。本例中的最后一行,調(diào)用 TransactionScope Complete 方法,將導(dǎo)致退出該塊時(shí)請(qǐng)求提交該事務(wù)。此方法還提供了內(nèi)置的錯(cuò)誤處理,出現(xiàn)異常時(shí)會(huì)終止事務(wù)。

                                     (示例位置:光盤\code\ch05\04\ClassTran\OrderData3

using (TransactionScope ts = new TransactionScope())//使整個(gè)代碼塊成為事務(wù)性代碼

{

    #region 在這里編寫需要具備Transaction的代碼

    string msg = "";

    string conString = "data source=127.0.0.1;database=codematic;user id=sa;

password=";

    SqlConnection myConnection = new SqlConnection(conString);

    myConnection.Open();

    SqlCommand myCommand = new SqlCommand();

    myCommand.Connection = myConnection;

    try

    {

        myCommand.CommandText = "update P_Product set Name='電腦2' where Id=52";

        myCommand.ExecuteNonQuery();

        myCommand.CommandText = "update P_Product set Name='電腦3' where Id=53";

        myCommand.ExecuteNonQuery();

        msg = "成功!";

    }

    catch (Exception ex)

    {

        msg = "失敗:" + ex.Message;

    }

    finally

    {

        myConnection.Close();

    }

    #endregion

    ts.Complete();

    return msg;              

}           

上面的代碼演示了在一個(gè)Transaction Scope里面打開一個(gè)數(shù)據(jù)庫連接的過程。這個(gè)數(shù)據(jù)庫連接由于處在一個(gè)Transaction Scope里面,所以會(huì)自動(dòng)獲得Transaction的能力。如果這里數(shù)據(jù)庫連接的是SQL Server 2005,那么這個(gè)Transaction將不會(huì)激活一個(gè)MSDTC管理的分布式事務(wù),而是會(huì)由.NET創(chuàng)建一個(gè)Local Transaction,性能非常高。但是如果是SQL Server 2000,則會(huì)自動(dòng)激活一個(gè)分布式事務(wù),在性能上會(huì)受一定的損失。

再看下面的例子:

void MethodMoreConn()

{

    using (TransactionScope ts = new TransactionScope())

    {

        using (SqlConnection conn = new SqlConnection(conString1))

        {

            conn.Open();

            using (SqlConnection conn2 = new SqlConnection(conString2))

            {

                conn2.Open();

            }

        }

        ts.Complete();

    }

}

這個(gè)例子更加充分地說明了Transaction Scope的強(qiáng)大,兩個(gè)數(shù)據(jù)庫連接!雖然上面的connconn2是兩個(gè)不同的連接對(duì)象,可能分別連接到不同的數(shù)據(jù)庫,但是由于它們處在一個(gè)TransactionScope中,它們就具備了“聯(lián)動(dòng)”的Transaction能力。在這里,將自動(dòng)激活一個(gè)MSDTC管理的分布式事務(wù)(可以通過打開【管理工具】里面的組件服務(wù),來查看當(dāng)前的分布式事務(wù)列表)。

1.在分布式事務(wù)中登記

ADO.NET 2.0 中的新增功能支持使用 EnlistTransaction 方法在分布式事務(wù)中登記。由于 EnlistTransaction Transaction 實(shí)例中登記連接,因此,該方法利用 System.Transactions 命名空間中的可用功能來管理分布式事務(wù),從而比使用 System.EnterpriseServices. ITransaction 對(duì)象的 EnlistDistributedTransaction 更可取。此外,其語義也稍有不同:在一個(gè)事務(wù)中顯式登記了某個(gè)連接后,如果第一個(gè)事務(wù)尚未完成,則無法取消登記或在另一個(gè)事務(wù)中登記該連接。

void MethodEnlist()

{

    CommittableTransaction tx = new CommittableTransaction();

    using (SqlConnection conn = new SqlConnection(conString))

    {

        conn.EnlistTransaction(tx);

    }

    tx.Commit();

}

2.實(shí)現(xiàn)嵌套事務(wù)范圍

void RootMethod()

{

    using (TransactionScope scope = new TransactionScope())

    {

        //操作代碼

        SonMethod();//子事務(wù)方法

        scope.Complete();

    }

}

void SonMethod()

{

    using (TransactionScope scope = new TransactionScope())

    {

        //操作代碼

        scope.Complete();

    }

}

3.事務(wù)范圍附加選項(xiàng)

如果你想要保留代碼部分執(zhí)行的操作,并且在操作失敗的情況下不希望中止環(huán)境事務(wù),則Suppress對(duì)你很有幫助。例如,在你想要執(zhí)行日志記錄或?qū)徍瞬僮鲿r(shí),不管你的環(huán)境事務(wù)是提交還是中止,上述值都很有用。該值允許你在事務(wù)范圍內(nèi)具有非事務(wù)性的代碼部分,如以下示例所示。

void MethodSuppress()

{

    using (TransactionScope scope1 = new TransactionScope())//開始事務(wù)

    {

        try

        {

           //開始一個(gè)非事務(wù)范圍

            using (TransactionScope scope2 = new TransactionScope(

               TransactionScopeOption.Suppress))

            {

                //不受事務(wù)控制代碼

            }

            //從這里開始又回歸事務(wù)處理

        }

        catch

        { }       

   }

}

雖然.NET 2.0對(duì)事務(wù)提供了很好的支持,但是沒有必要總是使用事務(wù)。使用事務(wù)的第一條規(guī)則是,在能夠使用事務(wù)的時(shí)候都應(yīng)該使用事務(wù),但是不要使用過度。原因在于,每次使用事務(wù)都會(huì)占用一定的開銷。另外,事務(wù)可能會(huì)鎖定一些表的行。還有一條規(guī)則是,只有當(dāng)操作需要的時(shí)候才使用事務(wù)。例如,如果只是從數(shù)據(jù)庫中查詢一些記錄,或者執(zhí)行單個(gè)查詢,則在大部分時(shí)候都不需要使用顯式事務(wù)。

開發(fā)人員應(yīng)該在頭腦中始終保持一個(gè)概念,就是用于修改多個(gè)不同表數(shù)據(jù)的冗長事務(wù)會(huì)嚴(yán)重妨礙系統(tǒng)中的所有其他用戶。這很可能導(dǎo)致一些性能問題。當(dāng)實(shí)現(xiàn)一個(gè)事務(wù)時(shí),遵循下面的實(shí)踐經(jīng)驗(yàn)?zāi)軌蜻_(dá)到可接受的結(jié)果:

避免使用在事務(wù)中的Select返回?cái)?shù)據(jù),除非語句依賴于返回?cái)?shù)據(jù)。

如果使用Select語句,則只選擇需要的行,這樣不會(huì)鎖定過多的資源,而盡可能地提高性能。

盡量將事務(wù)全部寫在T-SQL或者API中。

避免事務(wù)與多重獨(dú)立的批處理工作結(jié)合,應(yīng)該將這些批處理放置在單獨(dú)的事務(wù)中。

盡可能避免大量更新。

另外,必須注意的一點(diǎn)就是事務(wù)的默認(rèn)行為。在默認(rèn)情況下,如果沒有顯式地提交事務(wù),則事務(wù)會(huì)回滾。雖然默認(rèn)行為允許事務(wù)的回滾,但是顯式回滾方法總是一個(gè)良好的編程習(xí)慣。這不僅僅只是釋放鎖定數(shù)據(jù),也將使得代碼更容易讀取并且更少錯(cuò)誤。

      .NET提供的事務(wù)功能很強(qiáng)大,具體的內(nèi)容遠(yuǎn)不止本文所講解的這樣簡單。本文只是起到一個(gè)拋磚引玉的功能。希望讀者能夠靈活恰當(dāng)?shù)厥褂檬聞?wù)功能,而不要過度使用事務(wù),否則可能會(huì)對(duì)性能起到消極的作用。 

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多