在C#中使用COM+实现事务控制
生活随笔
收集整理的這篇文章主要介紹了
在C#中使用COM+实现事务控制
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
.NET技術(shù)是微軟大力推廣的下一代平臺(tái)技術(shù),自從.NET技術(shù)架構(gòu)的正式發(fā)布,此項(xiàng)技術(shù)也逐漸走向成熟和穩(wěn)定。按照微軟的平臺(tái)系統(tǒng)占有率,我們不難想象得到,在未來(lái)的一兩年內(nèi).NET技術(shù)必定會(huì)勢(shì)如破竹一般的登上主流的技術(shù)平臺(tái),而一個(gè)新的技術(shù)平臺(tái)得以快速發(fā)展的最重要的前提是:他不會(huì)徹底的摒棄以前的技術(shù),這一點(diǎn)對(duì)于.NET技術(shù)來(lái)說(shuō)指的就是COM/COM+技術(shù)了。?
?一般來(lái)說(shuō),在IT技術(shù)界以及硬件產(chǎn)業(yè),技術(shù)的更新?lián)Q代速度非常得驚人,而慣例是所有的新技術(shù)都會(huì)遵循向下兼容的原則,但是.NET技術(shù)不僅僅做到了這一點(diǎn),.NET甚至實(shí)現(xiàn)了相互之間的各自調(diào)用,這一點(diǎn)是非常難能可貴的。也就是說(shuō),不但我們可以在.NET組件中調(diào)用COM組件,同時(shí)也可以在COM組件中正常的調(diào)用.NET組件。這點(diǎn)帶來(lái)的好處是顯而易見(jiàn)的,一方面我們可以保持現(xiàn)有的技術(shù)資源,另一方面,在現(xiàn)有資源中可以利用.NET所帶來(lái)的各種新技術(shù)。?
?一般的數(shù)據(jù)庫(kù)事務(wù)控制要求事務(wù)里所做的操作必須在同一個(gè)數(shù)據(jù)庫(kù)內(nèi),這樣在出現(xiàn)錯(cuò)誤的時(shí)候才能回滾(RllBack)到初始狀態(tài)。這就存在一個(gè)問(wèn)題,在分布式應(yīng)用程序中,我們往往需要同時(shí)操作多個(gè)數(shù)據(jù)庫(kù),使用數(shù)據(jù)庫(kù)本身的事務(wù)處理,很難滿(mǎn)足程序?qū)κ聞?wù)控制的要求。在COM+中,提供了完整的事務(wù)服務(wù),我們可以利用它來(lái)完成在分布式應(yīng)用程序中的事務(wù)控制。?
?具體過(guò)程如下?
?一:用VS.NET生成一個(gè)類(lèi)庫(kù)?。?
?二:添加對(duì)System.EnterpristServices的引用,具體步驟?
?菜單:(項(xiàng)目-添加引用-在.NET選項(xiàng)卡選擇System.EnterpristServices-確定)?
?三:構(gòu)建類(lèi)?
?1:源程序?
using?System;?
using?System.EnterpriseServices;?
using?System.Data.SqlClient;?
using?System.Reflection;?
namespace?COMPlusSamples?
{?
//表明需要事務(wù)支持?
[?Transaction(TransactionOption.Required)?]?
//聲明為服務(wù)器應(yīng)用程序,還可以選擇Library,表示為庫(kù)應(yīng)用程序?
[assembly:?ApplicationActivation(ActivationOption.Server)]?
//描述信息?
[assembly:?Description("sample")]?
public?class?TxCfgClass?:?ServicedComponent?
{?
private?static?string?init1?=?"user?id=sa;password=;initial?catalog=pubs;data?source=(local)";?
private?static?string?init2?=?"user?id=sa;password=;initial?catalog=NorthWind;data?source=(local)";?
private?static?string?add1?=?"insert?into?authors('au_lname','au_fname')?values('test1',?'test2')";?
private?static?string?add2?=?"insert?into?sample?values('test1',22)";?
//the?error?sql?statement?
//there?is?not?table?“sample”?
public?TxCfgClass()?{}?
private?void?ExecSQL(string?init,?string?sql)?
{?
SqlConnection?conn?=?new?SqlConnection(init);?
SqlCommand?cmd?=?conn.CreateCommand();?
cmd.CommandText?=?sql;?
conn.Open();?
cmd.ExecuteNonQuery();?
conn.Close();?
}?
//添加一條記錄到數(shù)據(jù)庫(kù)?
public?void?Add()?
{?
try?
{?
//在一數(shù)據(jù)庫(kù)中插入一條記錄?
ExecSQL(init1,?add1);?
Console.WriteLine("the?operation?in?the?same?database?completely");?
//在另外一個(gè)數(shù)據(jù)庫(kù)中插入兩條記錄?
//這次執(zhí)行的是一個(gè)錯(cuò)誤的SQL語(yǔ)句?
ExecSQL(init2,?add2);?
Console.WriteLine("the?operation?in?the?other?database?
completely");?
Console.WriteLine("Record(s)?added,?press?enter...");?
Console.Read();?
}?
catch(Exception?e)?
{?
//事務(wù)回滾?
ContextUtil.SetAbort();?
Console.WriteLine("Because?there?are?some?errors?in?the?operation?,so?transcation?abort");?
Console.WriteLine("The?error?is?"?+?e.Message);?
Console.WriteLine("abort?successfully");?
Console.Read();?
}?
}?
}?
}?
?2:程序說(shuō)明:?
?添加命名空間?using?System.EnterpriseServices;因?yàn)楸境绦蚴褂昧似渲械腃ontextUtil類(lèi)?
[?Transaction(TransactionOption.Required)?]?說(shuō)明DLL需要事務(wù)支持。?
?本程序的TxCfgClass?類(lèi)從ServicedComponent類(lèi)中繼承,這樣并不會(huì)影響該類(lèi),而只是在該類(lèi)中添加了兩個(gè)額外的方法,這兩個(gè)方法可以使代碼共享變得更加容易。?
?程序使用的sql?server數(shù)據(jù)庫(kù)在本機(jī)運(yùn)行,init1?和?init2是兩個(gè)連接數(shù)據(jù)庫(kù)的連接字符串,init連接pubs數(shù)據(jù)庫(kù),inin2連接northwind數(shù)據(jù)庫(kù),這是sql2000中自帶的示例數(shù)據(jù)庫(kù)。add1和add2是兩條sql語(yǔ)句,作用是分別向兩個(gè)數(shù)據(jù)庫(kù)的表里添加一條記錄。注意:add2是一條錯(cuò)誤的語(yǔ)句,因?yàn)楦緵](méi)有sample表,這樣,會(huì)在執(zhí)行時(shí)引起異常。(這正是我們所期望的)?
?在執(zhí)行到add2語(yǔ)句時(shí),由于它是錯(cuò)誤的,所以會(huì)引發(fā)異常,轉(zhuǎn)到錯(cuò)誤處理語(yǔ)句里來(lái)執(zhí)行。?
?ContextUtil.SetAbort();該語(yǔ)句使所有的數(shù)據(jù)庫(kù)操作回滾,這樣add1語(yǔ)句所插入的記錄也將不存在。(達(dá)到預(yù)期目標(biāo))?
?四:給程序添加強(qiáng)名(strong?name)?
?1:創(chuàng)建一對(duì)密鑰?
?用來(lái)創(chuàng)建密鑰的工具是稱(chēng)為sn.exe的共享工具。通常通過(guò)命令提示運(yùn)行它,該工具可執(zhí)行各種任務(wù)以生成并提取密鑰。我們需要用以下方式來(lái)運(yùn)行sn.exe。?
sn?–k?key.snk?
?其中key.snk?代表將保存密鑰的文件的名稱(chēng)。它的名稱(chēng)可以是任意的,不過(guò)習(xí)慣上帶有.snk后綴名。?
?2:簽名?
?簽名通常是在編譯時(shí)進(jìn)行的。簽名時(shí),用戶(hù)可利用C#屬性通知編譯器應(yīng)該使用正確的密鑰文件對(duì)DLL進(jìn)行簽名。要做到這一點(diǎn)用戶(hù)需要打開(kāi)工程中的AssemblyInfo.cs文件并進(jìn)行修改。?
?[assembly:AssemblyKeyFile(“..//..//key.snk”)]?
?注:key.snk文件和項(xiàng)目文件在同一個(gè)文件夾?
?五:編譯成DLL?(具體步驟)?
?菜單:(生成-生成)?
?如果一切正常,就會(huì)生成DLL文件?
?六:使用regsvcs.exe將Dll注冊(cè)到COM+?Services里面?
?我們需要用以下方式運(yùn)行regsvcs.exe?
?regsvcs?dll文件名?
?如果一切正常的話,regsvcs.exe就會(huì)把dll輸入到COM+?Services中。?
?至此,我們已經(jīng)生成并注冊(cè)了這個(gè)可以由其它程序使用的類(lèi),現(xiàn)在,我們來(lái)寫(xiě)一個(gè)控制臺(tái)程序來(lái)檢驗(yàn)這個(gè)類(lèi)是否正常運(yùn)行?
?七:構(gòu)建客戶(hù)機(jī)?
?1:新建控制臺(tái)應(yīng)用程序項(xiàng)目?
?菜單(文件-新建-項(xiàng)目)?
?選擇控制臺(tái)應(yīng)用程序?,并選擇?添入解決方案?,確定?
?2:同上面的第二步一樣,添加對(duì)System.EnterpriseServices的引用。?
?3:添加對(duì)自己剛才做好的類(lèi)的引用。?
?菜單(項(xiàng)目-添加引用-瀏覽),選擇剛才生成的DLL,確定?
?4:輸入以下程序?
using?System;?
using?COMPlusSamples;?
using?System.EnterpriseServices;?
public?class?Client?
{?
public?static?void?Main()?
{?
TxCfgClass?cfg?=?new?TxCfgClass();?
cfg.Add();?
}?
}?
?5:將控制臺(tái)程序設(shè)置為啟動(dòng)項(xiàng),然后編譯運(yùn)行,就會(huì)看到結(jié)果。?
?正如我們希望的,第一條記錄沒(méi)有插入數(shù)據(jù)庫(kù)?
?一般來(lái)說(shuō),在IT技術(shù)界以及硬件產(chǎn)業(yè),技術(shù)的更新?lián)Q代速度非常得驚人,而慣例是所有的新技術(shù)都會(huì)遵循向下兼容的原則,但是.NET技術(shù)不僅僅做到了這一點(diǎn),.NET甚至實(shí)現(xiàn)了相互之間的各自調(diào)用,這一點(diǎn)是非常難能可貴的。也就是說(shuō),不但我們可以在.NET組件中調(diào)用COM組件,同時(shí)也可以在COM組件中正常的調(diào)用.NET組件。這點(diǎn)帶來(lái)的好處是顯而易見(jiàn)的,一方面我們可以保持現(xiàn)有的技術(shù)資源,另一方面,在現(xiàn)有資源中可以利用.NET所帶來(lái)的各種新技術(shù)。?
?一般的數(shù)據(jù)庫(kù)事務(wù)控制要求事務(wù)里所做的操作必須在同一個(gè)數(shù)據(jù)庫(kù)內(nèi),這樣在出現(xiàn)錯(cuò)誤的時(shí)候才能回滾(RllBack)到初始狀態(tài)。這就存在一個(gè)問(wèn)題,在分布式應(yīng)用程序中,我們往往需要同時(shí)操作多個(gè)數(shù)據(jù)庫(kù),使用數(shù)據(jù)庫(kù)本身的事務(wù)處理,很難滿(mǎn)足程序?qū)κ聞?wù)控制的要求。在COM+中,提供了完整的事務(wù)服務(wù),我們可以利用它來(lái)完成在分布式應(yīng)用程序中的事務(wù)控制。?
?具體過(guò)程如下?
?一:用VS.NET生成一個(gè)類(lèi)庫(kù)?。?
?二:添加對(duì)System.EnterpristServices的引用,具體步驟?
?菜單:(項(xiàng)目-添加引用-在.NET選項(xiàng)卡選擇System.EnterpristServices-確定)?
?三:構(gòu)建類(lèi)?
?1:源程序?
using?System;?
using?System.EnterpriseServices;?
using?System.Data.SqlClient;?
using?System.Reflection;?
namespace?COMPlusSamples?
{?
//表明需要事務(wù)支持?
[?Transaction(TransactionOption.Required)?]?
//聲明為服務(wù)器應(yīng)用程序,還可以選擇Library,表示為庫(kù)應(yīng)用程序?
[assembly:?ApplicationActivation(ActivationOption.Server)]?
//描述信息?
[assembly:?Description("sample")]?
public?class?TxCfgClass?:?ServicedComponent?
{?
private?static?string?init1?=?"user?id=sa;password=;initial?catalog=pubs;data?source=(local)";?
private?static?string?init2?=?"user?id=sa;password=;initial?catalog=NorthWind;data?source=(local)";?
private?static?string?add1?=?"insert?into?authors('au_lname','au_fname')?values('test1',?'test2')";?
private?static?string?add2?=?"insert?into?sample?values('test1',22)";?
//the?error?sql?statement?
//there?is?not?table?“sample”?
public?TxCfgClass()?{}?
private?void?ExecSQL(string?init,?string?sql)?
{?
SqlConnection?conn?=?new?SqlConnection(init);?
SqlCommand?cmd?=?conn.CreateCommand();?
cmd.CommandText?=?sql;?
conn.Open();?
cmd.ExecuteNonQuery();?
conn.Close();?
}?
//添加一條記錄到數(shù)據(jù)庫(kù)?
public?void?Add()?
{?
try?
{?
//在一數(shù)據(jù)庫(kù)中插入一條記錄?
ExecSQL(init1,?add1);?
Console.WriteLine("the?operation?in?the?same?database?completely");?
//在另外一個(gè)數(shù)據(jù)庫(kù)中插入兩條記錄?
//這次執(zhí)行的是一個(gè)錯(cuò)誤的SQL語(yǔ)句?
ExecSQL(init2,?add2);?
Console.WriteLine("the?operation?in?the?other?database?
completely");?
Console.WriteLine("Record(s)?added,?press?enter...");?
Console.Read();?
}?
catch(Exception?e)?
{?
//事務(wù)回滾?
ContextUtil.SetAbort();?
Console.WriteLine("Because?there?are?some?errors?in?the?operation?,so?transcation?abort");?
Console.WriteLine("The?error?is?"?+?e.Message);?
Console.WriteLine("abort?successfully");?
Console.Read();?
}?
}?
}?
}?
?2:程序說(shuō)明:?
?添加命名空間?using?System.EnterpriseServices;因?yàn)楸境绦蚴褂昧似渲械腃ontextUtil類(lèi)?
[?Transaction(TransactionOption.Required)?]?說(shuō)明DLL需要事務(wù)支持。?
?本程序的TxCfgClass?類(lèi)從ServicedComponent類(lèi)中繼承,這樣并不會(huì)影響該類(lèi),而只是在該類(lèi)中添加了兩個(gè)額外的方法,這兩個(gè)方法可以使代碼共享變得更加容易。?
?程序使用的sql?server數(shù)據(jù)庫(kù)在本機(jī)運(yùn)行,init1?和?init2是兩個(gè)連接數(shù)據(jù)庫(kù)的連接字符串,init連接pubs數(shù)據(jù)庫(kù),inin2連接northwind數(shù)據(jù)庫(kù),這是sql2000中自帶的示例數(shù)據(jù)庫(kù)。add1和add2是兩條sql語(yǔ)句,作用是分別向兩個(gè)數(shù)據(jù)庫(kù)的表里添加一條記錄。注意:add2是一條錯(cuò)誤的語(yǔ)句,因?yàn)楦緵](méi)有sample表,這樣,會(huì)在執(zhí)行時(shí)引起異常。(這正是我們所期望的)?
?在執(zhí)行到add2語(yǔ)句時(shí),由于它是錯(cuò)誤的,所以會(huì)引發(fā)異常,轉(zhuǎn)到錯(cuò)誤處理語(yǔ)句里來(lái)執(zhí)行。?
?ContextUtil.SetAbort();該語(yǔ)句使所有的數(shù)據(jù)庫(kù)操作回滾,這樣add1語(yǔ)句所插入的記錄也將不存在。(達(dá)到預(yù)期目標(biāo))?
?四:給程序添加強(qiáng)名(strong?name)?
?1:創(chuàng)建一對(duì)密鑰?
?用來(lái)創(chuàng)建密鑰的工具是稱(chēng)為sn.exe的共享工具。通常通過(guò)命令提示運(yùn)行它,該工具可執(zhí)行各種任務(wù)以生成并提取密鑰。我們需要用以下方式來(lái)運(yùn)行sn.exe。?
sn?–k?key.snk?
?其中key.snk?代表將保存密鑰的文件的名稱(chēng)。它的名稱(chēng)可以是任意的,不過(guò)習(xí)慣上帶有.snk后綴名。?
?2:簽名?
?簽名通常是在編譯時(shí)進(jìn)行的。簽名時(shí),用戶(hù)可利用C#屬性通知編譯器應(yīng)該使用正確的密鑰文件對(duì)DLL進(jìn)行簽名。要做到這一點(diǎn)用戶(hù)需要打開(kāi)工程中的AssemblyInfo.cs文件并進(jìn)行修改。?
?[assembly:AssemblyKeyFile(“..//..//key.snk”)]?
?注:key.snk文件和項(xiàng)目文件在同一個(gè)文件夾?
?五:編譯成DLL?(具體步驟)?
?菜單:(生成-生成)?
?如果一切正常,就會(huì)生成DLL文件?
?六:使用regsvcs.exe將Dll注冊(cè)到COM+?Services里面?
?我們需要用以下方式運(yùn)行regsvcs.exe?
?regsvcs?dll文件名?
?如果一切正常的話,regsvcs.exe就會(huì)把dll輸入到COM+?Services中。?
?至此,我們已經(jīng)生成并注冊(cè)了這個(gè)可以由其它程序使用的類(lèi),現(xiàn)在,我們來(lái)寫(xiě)一個(gè)控制臺(tái)程序來(lái)檢驗(yàn)這個(gè)類(lèi)是否正常運(yùn)行?
?七:構(gòu)建客戶(hù)機(jī)?
?1:新建控制臺(tái)應(yīng)用程序項(xiàng)目?
?菜單(文件-新建-項(xiàng)目)?
?選擇控制臺(tái)應(yīng)用程序?,并選擇?添入解決方案?,確定?
?2:同上面的第二步一樣,添加對(duì)System.EnterpriseServices的引用。?
?3:添加對(duì)自己剛才做好的類(lèi)的引用。?
?菜單(項(xiàng)目-添加引用-瀏覽),選擇剛才生成的DLL,確定?
?4:輸入以下程序?
using?System;?
using?COMPlusSamples;?
using?System.EnterpriseServices;?
public?class?Client?
{?
public?static?void?Main()?
{?
TxCfgClass?cfg?=?new?TxCfgClass();?
cfg.Add();?
}?
}?
?5:將控制臺(tái)程序設(shè)置為啟動(dòng)項(xiàng),然后編譯運(yùn)行,就會(huì)看到結(jié)果。?
?正如我們希望的,第一條記錄沒(méi)有插入數(shù)據(jù)庫(kù)?
總結(jié)
以上是生活随笔為你收集整理的在C#中使用COM+实现事务控制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何使用 ASP.NET 实用工具加密凭
- 下一篇: SQL语句优化技术分析