在.net 1.1或者.net 2.0中要實現分布式事務,如果不涉及遠程調用,如調用remoting或者web service的方法,應該說是一件非常簡單的事情,只需要用COM+(1.1/ServiceDomain)或者TransactionScope(2.0),通過msdtc協調即可。
但是當事務方法中還需要調用remoting或者web service(不使用ws-at)時,由于remoting不支持事務傳播機制,因此即便客戶端調用remoting后發生錯誤回滾,remoting server上已經執行的操作(如數據庫操作)也已經無法回滾。
但是在一些特殊的應用中,數據完整性比性能更重要的情況下,如果希望客戶端回滾時,remoting server上執行的操作也可以回滾,那么可以使用msdtc的Transaction Internet Protocol(TIP)協議(事實上,msdtc除了支持常用的OleTx分布式事務協議外,還支持XA和TIP協議),讓客戶端啟動的事務“傳播”至Remoting Server,那樣只要Remoting Server同樣使用客戶端傳播過來的事務,即可實現Remoting下的分布式事務。具體的做法如下:
(1)由于TIP事務協議默認是不啟用的,所以第一步首先配置MSDTC支持TIP事務。在msdtc屬性頁中的點擊“安全配置”后選中“啟用TIP事務”。
(2)實現ITipTransaction 接口,用于從ContextUtil.Transaction查詢TIPTransaction的相關屬性。具體是獲取TIP事務的TIP URL屬性。
ITipTransaction 接口的定義:
[ Guid("17CF72D0-BAC5-11d1-B1BF-00C04FC2F3EF") ]
[ InterfaceType(ComInterfaceType.InterfaceIsIUnknown) ]
public interface ITipTransaction
{
void Push([In, MarshalAs(UnmanagedType.LPStr)] string pszRemoteTmUrl,
[In, Out, MarshalAs(UnmanagedType.LPStr)] ref string ppszRemoteTxUrl);
![]()
void GetTransactionUrl([In, Out, MarshalAs(UnmanagedType.LPStr)]
ref string ppszLocalTxUrl);
}
獲取TIP URL的代碼:
string url = null;
ITipTransaction trxn = (ITipTransaction) ContextUtil.Transaction;
trxn.GetTransactionUrl(ref url);
(3)通過一定的機制,將獲取得到的TIP URL傳遞到Remoting服務器。
要將tip url傳遞到remoting server方法很多,可以通過參數傳遞過去,也可以通過callcontext傳遞過去,具體可以看附件的代碼。
(4)在Remoting Server中,利用TIP URL連接到客戶端的事務中,并啟動事務。
獲取到client傳遞過來的tip url后,就可以通過它連接到現有的事務協調器上,具體代碼:
TransactionCallContext ctx = (TransactionCallContext)CallContext.GetData("DTCTxID");
ServiceConfig config = new ServiceConfig();
if (ctx != null)
{
config.TipUrl = ctx.TipUrl;
config.Transaction = TransactionOption.RequiresNew;
}
else
{
config.Transaction = TransactionOption.Disabled;
}
using(TransactionScope scope = new TransactionScope(config))
{
rows = UpdatePoint();
![]()
if( rows > 0 )
{
scope.SetComplete();
}
}
通過上面的方式,就可以實現Remoting下的分布式事務了。
源代碼:
/Files/walkinhill/RemotingTransactionDemo.rar
參考文章:
http://dotnetjunkies.com/WebLog/chris.taylor/articles/54503.aspx
http://www.codeproject.com/csharp/complus_tip.asp
盡管通過上面的方式實現了remoting下的分布式事務,但是還是有些麻煩,而且一不小心還是會出錯的。相比之下,wcf內部已經實現了這樣的事務機制,而且只需要配置一下和外加一些特性就可以實現。而且還支持oletransactions和ws-at協議,看來以后用wcf方便多了。
最后有一點,這里只是了解了remoting下的分布式事務,但是具體要不要用,還是要充分考慮性能的問題,畢竟遠程調用對性能的消耗還是很大的,特別是事務下對資源的鎖導致的性能下降更嚴重:)
但是當事務方法中還需要調用remoting或者web service(不使用ws-at)時,由于remoting不支持事務傳播機制,因此即便客戶端調用remoting后發生錯誤回滾,remoting server上已經執行的操作(如數據庫操作)也已經無法回滾。
但是在一些特殊的應用中,數據完整性比性能更重要的情況下,如果希望客戶端回滾時,remoting server上執行的操作也可以回滾,那么可以使用msdtc的Transaction Internet Protocol(TIP)協議(事實上,msdtc除了支持常用的OleTx分布式事務協議外,還支持XA和TIP協議),讓客戶端啟動的事務“傳播”至Remoting Server,那樣只要Remoting Server同樣使用客戶端傳播過來的事務,即可實現Remoting下的分布式事務。具體的做法如下:
(1)由于TIP事務協議默認是不啟用的,所以第一步首先配置MSDTC支持TIP事務。在msdtc屬性頁中的點擊“安全配置”后選中“啟用TIP事務”。
(2)實現ITipTransaction 接口,用于從ContextUtil.Transaction查詢TIPTransaction的相關屬性。具體是獲取TIP事務的TIP URL屬性。
ITipTransaction 接口的定義:
[ Guid("17CF72D0-BAC5-11d1-B1BF-00C04FC2F3EF") ]
[ InterfaceType(ComInterfaceType.InterfaceIsIUnknown) ]
public interface ITipTransaction
{
void Push([In, MarshalAs(UnmanagedType.LPStr)] string pszRemoteTmUrl,
[In, Out, MarshalAs(UnmanagedType.LPStr)] ref string ppszRemoteTxUrl);
void GetTransactionUrl([In, Out, MarshalAs(UnmanagedType.LPStr)]
ref string ppszLocalTxUrl);
} 獲取TIP URL的代碼:
string url = null;
ITipTransaction trxn = (ITipTransaction) ContextUtil.Transaction;
trxn.GetTransactionUrl(ref url);

(3)通過一定的機制,將獲取得到的TIP URL傳遞到Remoting服務器。
要將tip url傳遞到remoting server方法很多,可以通過參數傳遞過去,也可以通過callcontext傳遞過去,具體可以看附件的代碼。
(4)在Remoting Server中,利用TIP URL連接到客戶端的事務中,并啟動事務。
獲取到client傳遞過來的tip url后,就可以通過它連接到現有的事務協調器上,具體代碼:
TransactionCallContext ctx = (TransactionCallContext)CallContext.GetData("DTCTxID");
ServiceConfig config = new ServiceConfig();
if (ctx != null)
{
config.TipUrl = ctx.TipUrl;
config.Transaction = TransactionOption.RequiresNew;
}
else
{
config.Transaction = TransactionOption.Disabled;
}
using(TransactionScope scope = new TransactionScope(config))
{
rows = UpdatePoint();
if( rows > 0 )
{
scope.SetComplete();
}
}源代碼:
/Files/walkinhill/RemotingTransactionDemo.rar
參考文章:
http://dotnetjunkies.com/WebLog/chris.taylor/articles/54503.aspx
http://www.codeproject.com/csharp/complus_tip.asp
盡管通過上面的方式實現了remoting下的分布式事務,但是還是有些麻煩,而且一不小心還是會出錯的。相比之下,wcf內部已經實現了這樣的事務機制,而且只需要配置一下和外加一些特性就可以實現。而且還支持oletransactions和ws-at協議,看來以后用wcf方便多了。
最后有一點,這里只是了解了remoting下的分布式事務,但是具體要不要用,還是要充分考慮性能的問題,畢竟遠程調用對性能的消耗還是很大的,特別是事務下對資源的鎖導致的性能下降更嚴重:)

浙公網安備 33010602011771號