1. 程式人生 > 實用技巧 >WCF分散式開發必備知識(3):Enterprise Services(企業服務與COM+)

WCF分散式開發必備知識(3):Enterprise Services(企業服務與COM+)

今天繼續我們<WCF分散式開發必備知識>系列文章第3節,通過前兩節的學習,我們已經掌握了MSMQ和.Net Remoting的概念和開發過程.今天我們來學習..Net分散式開發的另外一個技術:Enterpise Services.本節的基本結構是1.EnterpriseServices和COM+的基本概念.2.Enterprise Services中重要的類及特性3.Enterprise Services實現COM+事務的編碼\部署\測試過程.最後是總結.有興趣的可以看一下我翻譯的文章.經典技術文章翻譯(1):COM+整合:.NET Enterprise Services 如何幫你建立分散式應用 那麼現在我們就開始今天的學習,首先介紹的是: 一.基本概念 1.什麼是COM+ COM+的底層結構仍然以COM為基礎,它不僅具備了COM的易於使用者定製\可重用\簡化開發的優點,同時又避免了COM實現方面的一些不足.把COM、DCOM和MTS的程式設計模型結合起來,它通過作業系統的各種支援,使元件物件模型建立在應用層上,繼承了它們的絕大多數特性,增加了新的功能。
COM+的幾個主要特性: 比如佇列服務、負載平衡、記憶體資料庫、事件服務等。它更加註重於分散式網路應用的設計和實現(參考msdn)。 2.什麼是Enterpise Services Enterprise Services是微軟應用程式伺服器技術的別稱..Net Enterprise Services提供了可以在.Net 元件中使用的COM+服務.因為它也是基於以前的COM+技術,在.NET平臺上開發.NET元件,使用Enterprise Services可以將.NET元件並進行封裝為COM物件,這樣.NET元件就可以使用COM+服務了..NET做為新一代的開發平臺,實現了COM元件相互之間的呼叫,繼承了向前相容的優良傳統.同樣COM+可以呼叫.Net 元件,會給COM+服務帶來一些擴充套件.
二.Enterprise Services中重要的類及特性 Enterprise Servicesg工作在三層架構中的業務邏輯層或者資料訪問層.由於基於COM+技術,所以它也可以通過Micro Application Center Server實現負載均衡.下面我們來介紹一下Enterprise Services裡幾個重要的概念. (1)上下文(context又翻譯為環境):所有的COM+服務都是通過上下文(context又翻譯為環境)實現的,上下文是程序裡提供給物件執行時服務的空間.如果一個物件呼叫另外一個上下文裡的物件,這個方法呼叫會被代理擷取,COM執行時就可以利用代理來預處理或者遲處理請求並執行相關的服務程式碼.過程如圖1
圖1COM+服務與上下文 (2)自動事務處理(automatic transaction): Enterprise Services裡最常用的特性就是自動事務處理,這個一般在類的星星[Transaction]使用這個特性,就不需要再編寫複雜的程式碼來顯示執行事務準備工作,如物件的傳遞等,設定這個屬性後,上下文環境會在後臺進行設定.具體的設定在TransactionOption類的屬性裡選擇.Required表示共享一個事務,必要的時候建立一個新事務. (3)物件池(Obejct pooling): 這個屬性可以設定是需要物件池和物件池的大小.主要是考慮到物件的建立和銷燬會佔用更多的資源.使用物件池會事先建立物件,客戶的請求到來就直接到物件池裡查詢需要的物件,直接響應請求,可以提高服務的效能,節約時間. (4)ServicedComponent: 是所有使用COM+服務類的基類.ServicedComponent繼承自ContextBoundObject類.ContextBoundObject繼承自MarshalByRefObject.這個類在上一節的.Net Remoting介紹過,使支援remoting的程式可以跨程式域邊界的訪問物件. 另外還有分散式事務處理的等概念,Enterprise Services裡是使用DTC來實現的. 三.Enterprise Services實現COM+事務的編碼\部署\測試過程 上面我們熟悉了Enterprise Services的特性和一些重要的概念,下面我們就來利用Enterprise Services技術實現裡COM+事務處理.在分散式應用程式中,我們往往需要同時操作多個數據庫,使用資料庫本身的事務處理,很難滿足程式對事務控制的要求。 大家都知道事務具有ACID的特性:Aotomicity原子性\Consistency一致性\Isolation獨立性\Durability永久性.
原子性就是一組資料庫操作被視為一個單元。要麼所有的操作都成功;如果其中一個操作失敗,則整個事務失敗。事物失敗,不會提交更改。 具體的實現過程如下: 1.編寫Enterprise Services COM+事務服務元件: 首先我們使用Visual Studio 建立一個類庫專案,新增程式集System.EnterpriseServices的引用.新增類EnterpriseServicesCOMPlus繼承自ServicedComponent,確保可以使用COM+服務.名稱空間外設定程式集屬性.具體程式碼 InBlock.gif1using System;
InBlock.gif2using System.Collections.Generic;
InBlock.gif3using System.Text;
InBlock.gif4using System.Data;
InBlock.gif5using System.Data.SqlClient;
InBlock.gif6using System.EnterpriseServices;
InBlock.gif7[assembly: ApplicationName("FrankEnterpriseServicesTransactionTest")]//在元件服務瀏覽器裡的名稱
InBlock.gif8[assembly: Description("Coded By Frank Xu Lei 2/14/2009")]//在元件服務瀏覽器裡的描述資訊
InBlock.gif9[assembly: ApplicationActivation(ActivationOption.Server)]//啟動型別Library在建立程序裡啟用,執行在客戶程序,Server型別系統程序啟用,
InBlock.gif 10[assembly: ApplicationAccessControl(false)]//訪問設定,關閉後,使用者都可以訪問
InBlock.gif 11namespace EnterpriseServicesCOM
InBlock.gif 12{
InBlock.gif 13//每個伺服器元件必須繼承自類ServicedComponent,ServicedComponent類繼承自ContextBoundObject
InBlock.gif 14//這樣服務就可以繫結到.net環境上
InBlock.gif 15//
InBlock.gif 16[EventTrackingEnabled(true)]//允許監視,元件物件瀏覽器可以看到。預設關閉,因為會降低效能
InBlock.gif 17[Description("Coded By Frank Xu Lei For EnterpriseServices Transaction Test")]//元件物件瀏覽器顯示的描述資訊
InBlock.gif 18//[JustInTimeActivation(false)]//開啟或者關閉JIT啟動
InBlock.gif 19[ObjectPooling(true, 1, 10)]//是否啟用物件池,如果物件建立消耗更多的資源,可以考慮物件池
InBlock.gif 20[Transaction(TransactionOption.Supported)]//是否需要支援事務特性
InBlock.gif 21
InBlock.gif 22public class EnterpriseServicesCOMPlusTransaction : ServicedComponent
InBlock.gif 23{
InBlock.gif 24//建構函式
InBlock.gif 25public EnterpriseServicesCOMPlusTransaction()
InBlock.gif 26{
InBlock.gif 27
InBlock.gif 28}
InBlock.gif 29//新增使用者user資訊,姓名長度表name和address的長度都是10字元,user2的長度都是100字元,此處呼叫Ado.net據持久層方法
InBlock.gif 30//[AutoComplete]//設定方法屬性,自動更新方法呼叫的結果
InBlock.gif 31public bool AddUser(string name, string address)
InBlock.gif 32{
InBlock.gif 33//呼叫另外一個COM元件的方法,主要是測試事務的完整性
InBlock.gif 34SqlConnection Conn;
InBlock.gif 35try
InBlock.gif 36{
InBlock.gif 37//user,第1次執行的插入操作,欄位長度限制10個字元
InBlock.gif 38//使用DataSet嚮導建立方法操作資料庫,
InBlock.gif 39EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter _userTableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter();
InBlock.gif 40_userTableAdapter.Insert(name, address);
InBlock.gif 41/**/////user2,第2次執行的插入操作,欄位長度限制100個字元
InBlock.gif 42EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter _user2TableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter();
InBlock.gif 43_user2TableAdapter.Insert(name, address);
InBlock.gif 44//也可以自己寫程式碼實現資料庫的操作
InBlock.gif 45
InBlock.gif 46//SqlConnection Conn = new SqlConnection("Data Source=|DataDirectory|Database.sdf");
InBlock.gif 47//Conn.Open();
InBlock.gif 48/**///// //user,第1次執行的插入操作,欄位長度限制10個字元
InBlock.gif 49//SqlCommand sqlCommand = new SqlCommand("INSERT INTO [user] (name, address) VALUES (" + name + "," + address + ")");
InBlock.gif 50//sqlCommand.ExecuteNonQuery();
InBlock.gif 51/**/////user2,第2次執行的插入操作,欄位長度限制100個字元
InBlock.gif 52//sqlCommand.CommandText = "INSERT INTO [user2] (name, address) VALUES (" + name + "," + address + ")";
InBlock.gif 53//sqlCommand.ExecuteNonQuery();
InBlock.gif 54
InBlock.gif 55ContextUtil.SetComplete();//事務成功
InBlock.gif 56//Conn.Close();
InBlock.gif 57return true;
InBlock.gif 58}
InBlock.gif 59catch (Exception e)
InBlock.gif 60{
InBlock.gif 61ContextUtil.SetAbort();//失敗,事務回滾,終止
InBlock.gif 62return false;
InBlock.gif 63throw e;
InBlock.gif 64
InBlock.gif 65}
InBlock.gif 66finally
InBlock.gif 67{
InBlock.gif 68//if (Conn != null)
InBlock.gif 69//{
InBlock.gif 70//Conn.Dispose();//釋放資源
InBlock.gif 71//Conn = null;
InBlock.gif 72//}
InBlock.gif 73}
InBlock.gif 74}
InBlock.gif 75//更新資料庫的2個表,此處可以呼叫資料持久層方法
InBlock.gif 76//[AutoComplete]//設定方法屬性,自動更新方法呼叫的結果
InBlock.gif 77public bool UpdateUser(string name, string address, int id)
InBlock.gif 78{
InBlock.gif 79//呼叫另外一個COM元件的方法,主要是測試事務的完整性
InBlock.gif 80SqlConnection Conn;
InBlock.gif 81try
InBlock.gif 82{
InBlock.gif 83//使用DataSet嚮導建立方法操作資料庫,
InBlock.gif 84EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter _userTableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter();
InBlock.gif 85_userTableAdapter.Update(name,address,id);
InBlock.gif 86
InBlock.gif 87EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter _user2TableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter();
InBlock.gif 88_user2TableAdapter.Update(name, address, id);
InBlock.gif 89//也可以自己寫程式碼實現資料庫的操作
InBlock.gif 90//SqlConnection Conn = new SqlConnection("Data Source=|DataDirectory|Database.sdf");
InBlock.gif 91//Conn.Open();
InBlock.gif 92/**/////
InBlock.gif 93//SqlCommand sqlCommand = new SqlCommand("UPDATE [user] SET name = " + name + ", address =" + address + "WHERE (id =" + id + ")");
InBlock.gif 94//sqlCommand.ExecuteNonQuery();
InBlock.gif 95
InBlock.gif 96//sqlCommand.CommandText = "UPDATE [user2] SET name = " + name + ", address =" + address + "WHERE (id =" + id + ")";
InBlock.gif 97//sqlCommand.ExecuteNonQuery();
InBlock.gif 98
InBlock.gif 99ContextUtil.SetComplete();//事務成功
InBlock.gif100return true;
InBlock.gif101//Conn.Close();
InBlock.gif102}
InBlock.gif103catch (Exception e)
InBlock.gif104{
InBlock.gif105ContextUtil.SetAbort();//失敗,事務回滾,終止
InBlock.gif106return false;
InBlock.gif107throw e;
InBlock.gif108}
InBlock.gif109finally
InBlock.gif110{
InBlock.gif111//if (Conn != null)
InBlock.gif112//{
InBlock.gif113//Conn.Dispose();//釋放資源
InBlock.gif114//Conn = null;
InBlock.gif115//}
InBlock.gif116}
InBlock.gif117}
InBlock.gif118}
InBlock.gif119}