WCF分散式開發必備知識(3):Enterprise Services(企業服務與COM+)
阿新 • • 發佈:2020-10-13
今天繼續我們<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+服務.名稱空間外設定程式集屬性.具體程式碼 1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Data;
5using System.Data.SqlClient;
6using System.EnterpriseServices;
7[assembly: ApplicationName("FrankEnterpriseServicesTransactionTest")]//在元件服務瀏覽器裡的名稱
8[assembly: Description("Coded By Frank Xu Lei 2/14/2009")]//在元件服務瀏覽器裡的描述資訊
9[assembly: ApplicationActivation(ActivationOption.Server)]//啟動型別Library在建立程序裡啟用,執行在客戶程序,Server型別系統程序啟用,
10[assembly: ApplicationAccessControl(false)]//訪問設定,關閉後,使用者都可以訪問
11namespace EnterpriseServicesCOM
12{
13//每個伺服器元件必須繼承自類ServicedComponent,ServicedComponent類繼承自ContextBoundObject
14//這樣服務就可以繫結到.net環境上
15//
16[EventTrackingEnabled(true)]//允許監視,元件物件瀏覽器可以看到。預設關閉,因為會降低效能
17[Description("Coded By Frank Xu Lei For EnterpriseServices Transaction Test")]//元件物件瀏覽器顯示的描述資訊
18//[JustInTimeActivation(false)]//開啟或者關閉JIT啟動
19[ObjectPooling(true, 1, 10)]//是否啟用物件池,如果物件建立消耗更多的資源,可以考慮物件池
20[Transaction(TransactionOption.Supported)]//是否需要支援事務特性
21
22public class EnterpriseServicesCOMPlusTransaction : ServicedComponent
23{
24//建構函式
25public EnterpriseServicesCOMPlusTransaction()
26{
27
28}
29//新增使用者user資訊,姓名長度表name和address的長度都是10字元,user2的長度都是100字元,此處呼叫Ado.net據持久層方法
30//[AutoComplete]//設定方法屬性,自動更新方法呼叫的結果
31public bool AddUser(string name, string address)
32{
33//呼叫另外一個COM元件的方法,主要是測試事務的完整性
34SqlConnection Conn;
35try
36{
37//user,第1次執行的插入操作,欄位長度限制10個字元
38//使用DataSet嚮導建立方法操作資料庫,
39EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter _userTableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter();
40_userTableAdapter.Insert(name, address);
41/**/////user2,第2次執行的插入操作,欄位長度限制100個字元
42EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter _user2TableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter();
43_user2TableAdapter.Insert(name, address);
44//也可以自己寫程式碼實現資料庫的操作
45
46//SqlConnection Conn = new SqlConnection("Data Source=|DataDirectory|Database.sdf");
47//Conn.Open();
48/**///// //user,第1次執行的插入操作,欄位長度限制10個字元
49//SqlCommand sqlCommand = new SqlCommand("INSERT INTO [user] (name, address) VALUES (" + name + "," + address + ")");
50//sqlCommand.ExecuteNonQuery();
51/**/////user2,第2次執行的插入操作,欄位長度限制100個字元
52//sqlCommand.CommandText = "INSERT INTO [user2] (name, address) VALUES (" + name + "," + address + ")";
53//sqlCommand.ExecuteNonQuery();
54
55ContextUtil.SetComplete();//事務成功
56//Conn.Close();
57return true;
58}
59catch (Exception e)
60{
61ContextUtil.SetAbort();//失敗,事務回滾,終止
62return false;
63throw e;
64
65}
66finally
67{
68//if (Conn != null)
69//{
70//Conn.Dispose();//釋放資源
71//Conn = null;
72//}
73}
74}
75//更新資料庫的2個表,此處可以呼叫資料持久層方法
76//[AutoComplete]//設定方法屬性,自動更新方法呼叫的結果
77public bool UpdateUser(string name, string address, int id)
78{
79//呼叫另外一個COM元件的方法,主要是測試事務的完整性
80SqlConnection Conn;
81try
82{
83//使用DataSet嚮導建立方法操作資料庫,
84EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter _userTableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter();
85_userTableAdapter.Update(name,address,id);
86
87EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter _user2TableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter();
88_user2TableAdapter.Update(name, address, id);
89//也可以自己寫程式碼實現資料庫的操作
90//SqlConnection Conn = new SqlConnection("Data Source=|DataDirectory|Database.sdf");
91//Conn.Open();
92/**/////
93//SqlCommand sqlCommand = new SqlCommand("UPDATE [user] SET name = " + name + ", address =" + address + "WHERE (id =" + id + ")");
94//sqlCommand.ExecuteNonQuery();
95
96//sqlCommand.CommandText = "UPDATE [user2] SET name = " + name + ", address =" + address + "WHERE (id =" + id + ")";
97//sqlCommand.ExecuteNonQuery();
98
99ContextUtil.SetComplete();//事務成功
100return true;
101//Conn.Close();
102}
103catch (Exception e)
104{
105ContextUtil.SetAbort();//失敗,事務回滾,終止
106return false;
107throw e;
108}
109finally
110{
111//if (Conn != null)
112//{
113//Conn.Dispose();//釋放資源
114//Conn = null;
115//}
116}
117}
118}
119}
原子性就是一組資料庫操作被視為一個單元。要麼所有的操作都成功;如果其中一個操作失敗,則整個事務失敗。事物失敗,不會提交更改。 具體的實現過程如下: 1.編寫Enterprise Services COM+事務服務元件: 首先我們使用Visual Studio 建立一個類庫專案,新增程式集System.EnterpriseServices的引用.新增類EnterpriseServicesCOMPlus繼承自ServicedComponent,確保可以使用COM+服務.名稱空間外設定程式集屬性.具體程式碼 1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Data;
5using System.Data.SqlClient;
6using System.EnterpriseServices;
7[assembly: ApplicationName("FrankEnterpriseServicesTransactionTest")]//在元件服務瀏覽器裡的名稱
8[assembly: Description("Coded By Frank Xu Lei 2/14/2009")]//在元件服務瀏覽器裡的描述資訊
9[assembly: ApplicationActivation(ActivationOption.Server)]//啟動型別Library在建立程序裡啟用,執行在客戶程序,Server型別系統程序啟用,
10[assembly: ApplicationAccessControl(false)]//訪問設定,關閉後,使用者都可以訪問
11namespace EnterpriseServicesCOM
12{
13//每個伺服器元件必須繼承自類ServicedComponent,ServicedComponent類繼承自ContextBoundObject
14//這樣服務就可以繫結到.net環境上
15//
16[EventTrackingEnabled(true)]//允許監視,元件物件瀏覽器可以看到。預設關閉,因為會降低效能
17[Description("Coded By Frank Xu Lei For EnterpriseServices Transaction Test")]//元件物件瀏覽器顯示的描述資訊
18//[JustInTimeActivation(false)]//開啟或者關閉JIT啟動
19[ObjectPooling(true, 1, 10)]//是否啟用物件池,如果物件建立消耗更多的資源,可以考慮物件池
20[Transaction(TransactionOption.Supported)]//是否需要支援事務特性
21
22public class EnterpriseServicesCOMPlusTransaction : ServicedComponent
23{
24//建構函式
25public EnterpriseServicesCOMPlusTransaction()
26{
27
28}
29//新增使用者user資訊,姓名長度表name和address的長度都是10字元,user2的長度都是100字元,此處呼叫Ado.net據持久層方法
30//[AutoComplete]//設定方法屬性,自動更新方法呼叫的結果
31public bool AddUser(string name, string address)
32{
33//呼叫另外一個COM元件的方法,主要是測試事務的完整性
34SqlConnection Conn;
35try
36{
37//user,第1次執行的插入操作,欄位長度限制10個字元
38//使用DataSet嚮導建立方法操作資料庫,
39EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter _userTableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter();
40_userTableAdapter.Insert(name, address);
41/**/////user2,第2次執行的插入操作,欄位長度限制100個字元
42EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter _user2TableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter();
43_user2TableAdapter.Insert(name, address);
44//也可以自己寫程式碼實現資料庫的操作
45
46//SqlConnection Conn = new SqlConnection("Data Source=|DataDirectory|Database.sdf");
47//Conn.Open();
48/**///// //user,第1次執行的插入操作,欄位長度限制10個字元
49//SqlCommand sqlCommand = new SqlCommand("INSERT INTO [user] (name, address) VALUES (" + name + "," + address + ")");
50//sqlCommand.ExecuteNonQuery();
51/**/////user2,第2次執行的插入操作,欄位長度限制100個字元
52//sqlCommand.CommandText = "INSERT INTO [user2] (name, address) VALUES (" + name + "," + address + ")";
53//sqlCommand.ExecuteNonQuery();
54
55ContextUtil.SetComplete();//事務成功
56//Conn.Close();
57return true;
58}
59catch (Exception e)
60{
61ContextUtil.SetAbort();//失敗,事務回滾,終止
62return false;
63throw e;
64
65}
66finally
67{
68//if (Conn != null)
69//{
70//Conn.Dispose();//釋放資源
71//Conn = null;
72//}
73}
74}
75//更新資料庫的2個表,此處可以呼叫資料持久層方法
76//[AutoComplete]//設定方法屬性,自動更新方法呼叫的結果
77public bool UpdateUser(string name, string address, int id)
78{
79//呼叫另外一個COM元件的方法,主要是測試事務的完整性
80SqlConnection Conn;
81try
82{
83//使用DataSet嚮導建立方法操作資料庫,
84EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter _userTableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.userTableAdapter();
85_userTableAdapter.Update(name,address,id);
86
87EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter _user2TableAdapter = new EnterpriseServicesCOM.DatabaseDataSetTableAdapters.user2TableAdapter();
88_user2TableAdapter.Update(name, address, id);
89//也可以自己寫程式碼實現資料庫的操作
90//SqlConnection Conn = new SqlConnection("Data Source=|DataDirectory|Database.sdf");
91//Conn.Open();
92/**/////
93//SqlCommand sqlCommand = new SqlCommand("UPDATE [user] SET name = " + name + ", address =" + address + "WHERE (id =" + id + ")");
94//sqlCommand.ExecuteNonQuery();
95
96//sqlCommand.CommandText = "UPDATE [user2] SET name = " + name + ", address =" + address + "WHERE (id =" + id + ")";
97//sqlCommand.ExecuteNonQuery();
98
99ContextUtil.SetComplete();//事務成功
100return true;
101//Conn.Close();
102}
103catch (Exception e)
104{
105ContextUtil.SetAbort();//失敗,事務回滾,終止
106return false;
107throw e;
108}
109finally
110{
111//if (Conn != null)
112//{
113//Conn.Dispose();//釋放資源
114//Conn = null;
115//}
116}
117}
118}
119}