如何在 Visual C++.NET 元件或在 Visual C++ 2005年元件使用 COM + 交易

文章翻譯 文章翻譯
文章編號: 815814 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

摘要

本文將逐步告訴您,如何使用 COM + (元件服務) 在 Microsoft Visual C++.NET 類別或 Microsoft Visual C++ 2005年類別中的交易。一組的資料庫作業會被視為一個單位。可能是所有作業均都成功或者,如果一項作業失敗,整筆交易也會失敗。在後者的情況下而嘗試進行任何資料庫作業是不會張貼到基礎資料庫。

需求

本文假設您已熟悉下列主題:
  • 交易式的概念和處理
  • COM + (元件服務)

COM + 交易服務

您可以實作交易處理與 Microsoft.NET Framework 中 System.EnterpriseServices 命名空間。要存取 COM + 交易服務會建立類別。要這麼做,請您執行下列步驟:
  1. 啟動 Visual Studio.NET 或 Visual Studio 2005。
  2. 在 [檔案] 功能表上指向 [新增],然後按一下 [專案]。
  3. 在 [專案類型,按一下 [Visual C++ 專案,] 然後按一下 [範本] 下方的 [類別庫 (.NET)]。名稱專案 prjEnterprise。

    附註在 Visual 的 Studio 2005 中按一下 [專案類型,] 下的 [Visual C++],然後按一下 [範本] 下方的 [類別庫]。
  4. 在 [方案總管] 中以滑鼠右鍵按一下 [參考],然後按一下 [加入參考]。
  5. 按一下 [加入參考] 對話方塊中的 [NET] 索引標籤。
  6. 連按兩下 System.EnterpriseServices元件名稱] 下。
  7. 請確定 System.EnterpriseServices 出現在 選取的元件,下方,然後再按一下 [確定]
  8. 在 prjEnterprise.h 檔案中加入下列程式碼之前任何其他陳述式:
    using namespace System;
    using namespace System::Data;
    using namespace System::Data::SqlTypes;
    using namespace System::Data::Common;
    using namespace System::EnterpriseServices;
    using namespace System::Data::SqlClient;
    
  9. 加入名為 clsES prjEnterprise.h 檔案的新類別。
  10. 若要使用 COM + 交易式服務,請確定您的類別 (clsES) 繼承功能自 ServicedComponent 類別,如下所示:
    public __gc class clsES:public ServicedComponent
    
  11. 使用 交易 屬性指定的類別的交易支援層級,如下所示:
    [Transaction(TransactionOption::Required,Timeout=5)]public __gc class clsES:public ServicedComponent
    
  12. 在收到四個輸入的整數參數 clsES 類別中建立方法。名稱類別 dbAccess。前兩個參數會提供一個的產品 ID 和單位於該產品的順序。其次兩個參數會提供該產品的產品 ID 和庫存單位。這個方法會執行一組的資料庫作業對要被視為交易這些指定的產品識別碼:
    public:	void dbAccess(int pID1, int onOrder, int pID2, int inStock)
  13. dbAccess] 方法中建立 SQL 連線物件的 [北風資料庫,然後再開啟連線。資料庫作業發生藉由使用下列資料庫:
    SqlConnection * Conn = new SqlConnection("user id=<username>;password=<password>;Initial Catalog=northwind;Data Source=<Your SQL Server name>;");
    Conn->Open();
    注意 記住,若要變更以反映正確的值為您的 SQL Server 伺服器的連接字串參數。
  14. 設定要擷取資料庫處理期間,可能會發生任何例外狀況的 try 區塊。您必須攔截這些例外狀況來中止交易。try 區塊包括兩個資料庫作業。每個作業會更新指定的產品表格記錄中的不同欄位。
    try { 
    
  15. 執行到產品表格第一次更新。更新產品識別碼為前, 兩個輸入參數中所指定的 onOrder 值 [訂購量] 欄位。使用下列 SQL 命令執行這個 SQL 更新:
    SqlCommand * sqlCommand = new SqlCommand("UPDATE Products SET UnitsonOrder = @onOrderString WHERE productID = @pID1String ", Conn);
    sqlCommand->Parameters->Add(new SqlParameter("@onOrderString",SqlDbType::VarChar ,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,onOrder.ToString()));
    sqlCommand->Parameters->Add(new SqlParameter("@pID1String", SqlDbType::VarChar,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID1.ToString()));
    sqlCommand->ExecuteNonQuery();
    
  16. 執行另一個更新與產品] 資料表。更新 [庫存量] 欄位與 inStock 產品識別碼為,第三個和第四個輸入參數中所指定的值。使用下列 SQL 命令執行這個 SQL 更新:--> 加入參數 >
    sqlCommand->Parameters->Add(new SqlParameter("@inStockString",SqlDbType::VarChar ,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,inStock.ToString()));
    sqlCommand->Parameters->Add(new SqlParameter("@pID2String", SqlDbType::VarChar,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID2.ToString()));
    sqlCommand->ExecuteNonQuery();
    
  17. 由於這些更新是 COM + 交易的一部份,他們要認可視為一個單位。contextUtil 類別 System.EnterpriseServices 命名空間中的 setComplete 方法用來認可交易 (在這種情況下,兩個更新) 如果沒有錯誤已擲回:
    ContextUtil::SetComplete(); 
    
  18. 關閉到北風資料庫連線使用下列程式碼:
    Conn->Close(); }
    
  19. 您必須攔截,以便中止整筆交易在執行 SQL 命令發生任何例外狀況:
    catch(Exception * e){ 
    
  20. contextUtil 類別 System.EnterpriseServices 命名空間中的 setAbort 方法來中止整個交易。如果第一次更新成功,且第二個更新失敗,既非更新會張貼到 [產品] 表格。呼叫端指出交易失敗就會擲回已攔截的例外狀況:
    ContextUtil::SetAbort();
    throw e; }
    
  21. 為了正確執行這個元件,元件必須有強式名稱。產生強式名稱,然後簽署組件具有強式名稱。要這麼做,請您執行下列步驟:
    1. 在 [Visual Studio.NET 命令提示字元下鍵入 [sn.exe-k snEnterprise.snk 建立金鑰檔]。如需使用強式名稱簽署組件的詳細資訊,請參閱.NET Framework SDK 文件。
    2. 將 snEnterprise.snk 複製到您的專案資料夾。
    3. 在 AssemblyInfo.vc,新增下行程式碼之前或在其他組件屬性陳述式之後:
      [assembly:AssemblyKeyFileAttribute("..\\snEnterprise.snk")]; 
    4. 儲存,然後再建置您的專案。

完整的程式碼清單

附註 Remember to change your connection string parameters to reflect the correct values for your SQL Server server.
#pragma once

using namespace System;
using namespace System::Data;
using namespace System::Data::SqlTypes;
using namespace System::Data::Common;
using namespace System::EnterpriseServices;
using namespace System::Data::SqlClient;

namespace prjEnterprise
{
	
	[Transaction(TransactionOption::Required,Timeout=5)]
	public __gc class clsES:public ServicedComponent
	{
	public:	SqlConnection * Conn;

	public:	void dbAccess(int pID1, int onOrder, int pID2, int inStock)
		{
			try
			{			
				SqlConnection * Conn = new SqlConnection("user id=<username>;password=<password>;Initial Catalog=northwind;Data Source=<Your SQL Server name>;");
				Conn->Open();
				
				SqlCommand * sqlCommand = new SqlCommand("UPDATE Products SET UnitsonOrder = @onOrderString WHERE productID = @pID1String ", Conn);
				sqlCommand->Parameters->Add(new SqlParameter("@onOrderString",SqlDbType::VarChar ,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,onOrder.ToString()));
				sqlCommand->Parameters->Add(new SqlParameter("@pID1String", SqlDbType::VarChar,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID1.ToString()));
				sqlCommand->ExecuteNonQuery();
				
				sqlCommand->CommandText = "UPDATE Products SET UnitsinStock = @inStockString WHERE productID = @pID2String" ;
				sqlCommand->Parameters->Add(new SqlParameter("@inStockString",SqlDbType::VarChar ,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,inStock.ToString()));
				sqlCommand->Parameters->Add(new SqlParameter("@pID2String", SqlDbType::VarChar,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID2.ToString()));
				sqlCommand->ExecuteNonQuery();

				ContextUtil::SetComplete();
				Conn->Close();
			}
			catch(Exception * e)
			{
				ContextUtil::SetAbort();
			
				throw e;
			}			
		}
	};


}
附註 您必須加入通用語言執行階段支援編譯器選項 (/ clr:oldSyntax) 來順利編譯先前的程式碼範例的 Visual C++ 2005年中。 若要在 Visual C++ 2005年中加入常用的語言執行階段支援編譯器選項,請依照下列步驟執行:
  1. 按一下 [專案,] 然後按一下 [<ProjectName> 屬性

    附註<ProjectName> 是專案的名稱的預留位置。
  2. 展開 [組態屬性,] 然後按一下 [一般
  3. 按一下以選取 通用語言執行階段支援、 舊語法 (/ clr:oldSyntax)通用語言執行階段支援 的專案設定中在右窗格中,按一下 套用,],然後再按一下 [確定]
如需有關通用語言執行階段支援編譯器選項,請造訪下列 Microsoft 網站:
/ clr (通用語言執行階段編譯)
http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

請確認它可以運作

若要測試此程式碼,建立使用 clsES 類別的主控台應用程式專案。一種情況交易成功,然後更新 [訂購量] 和 [庫存量] 欄位指定的產品。在第二種情況下的 [訂購量] 欄位為指定的產品更新成功,但是 庫存量] 欄位為產品的更新動作會失敗,因為指定的產品編號不存在 [產品] 資料表中。這樣會造成交易失敗,而且交易將會被忽略。
  1. 啟動 Visual Studio.NET 或 Visual Studio 2005。
  2. 在 [檔案] 功能表上指向 [新增],然後按一下 [專案]。
  3. 在 [專案類型 下, 按一下 [Visual C++ 專案,] 然後按一下 [範本] 下方的 [主控台應用程式 (.NET)]。

    附註在 Visual 的 Studio 2005 中按一下 [專案類型,] 下的 [Visual C++],然後按一下 [範本] 下方的 [CLR 主控台應用程式]。
  4. 在 [名稱] 文字方塊中,輸入 testES。請確定已選取 [新增至方案] 選項。
  5. 按一下 [確定]],將這個專案加入至方案。
  6. 如要測試 prjEnterprisetestES,您必須將參考加入。在 [方案總管] 中以滑鼠右鍵按一下 testES (您剛新增) 的在 [參考],然後按一下 [加入參考]。
  7. 出現 [加入參考] 對話方塊。在 [專案] 索引標籤中,按兩下 prjEnterprise
  8. 參考出現在下方 選定元件。按一下 [確定]],將加入這個專案的參考。
  9. 將參考加入至專案 System.EnterpriseServices 命名空間。在 [方案總管] 中以滑鼠右鍵按一下 [參考],然後按一下 [加入參考]。
  10. 出現 [加入參考] 對話方塊。 在 [.NET] 索引標籤上的 元件名稱,] 下連按兩下 System.EnterpriseServices
  11. 請確定 System.EnterpriseServices 出現在 [選取的元件。按一下 [確定]
  12. testES,] 上按一下滑鼠右鍵,然後按一下 [設定為啟始專案]。
  13. 下列來源程式碼貼 testES 類別的 _tmain() 函式中:
    prjEnterprise::clsES * myTest = new prjEnterprise::clsES();	
    try 
    {
    	myTest->dbAccess(1, 777, 2, 888);
    	Console::WriteLine("TRANSACTION ONE -- SUCCESS");
    
    		myTest->dbAccess(1, 5, 2, -20);
    	Console::WriteLine("TRANSACTION TWO -- SUCCESS");
    }
    catch (Exception * e)
    {
    	Console::WriteLine("TRANSACTION FAILURE");
    	//Console::WriteLine("Error Message: {0}",e->Message);	 
    	//uncomment this line if you must get detailed error information
    }
    
  14. 按下 F5 以執行測試程式碼。

    在步驟 7 中程式碼,dbAccess 第一次呼叫會成功。產品 1 和產品 2 是在 [產品] 資料表中。產品 1 onOrder 欄位會更新以 777,以及 inStock 欄位到 888 更新產品 2。因為此交易成功,您在 [輸出] 視窗中收到下列訊息:
    交易一位成功
    dbAccess 到第二個呼叫會失敗。因此,dbAccess 至產品資料表中的都不更新陳述式會回傳到資料庫。雖然產品 1 可能有其 訂購量] 欄位更新為 5,產品 2 不能有其 庫存量] 欄位設定為 -20。因為在產品資料表定義中定義的條件約束的 庫存量 不允許有負數。因此,dbAccess 這個呼叫會失敗,且整筆交易失敗。[產品] 表格會保持對 dbAccess 呼叫前。catch 陳述式會處理從 dbAccess,交易失敗的通知,並且您在 [輸出] 視窗中收到下列錯誤訊息:
    交易失敗
  15. 使用 SQL Server 企業管理員檢查北風產品] 資料表的內容。當您檢視產品 1 時,[訂購量] 欄位等於 777。當您檢視產品 2 時,[庫存量] 欄位會是 888。因此,dbAccess (這會造成這些欄位不同的值) 至第二個呼叫會失敗。

疑難排解

  • 請確定使用 COM + 服務的專案具有強式名稱。
  • 使用 COM + 服務的任何類別必須繼承自服務元件。服務的元件位於 System.EnterpriseServices 命名空間中。
  • 偵錯,時可能會在逾時間交易認可或中止之前。若要避免逾時,使用 [交易屬性上的 [逾時內容]。在下列範例相關聯的方法具有 1,200 秒鐘才能完成任何交易,才算逾時:
    [Transaction(TransactionOption::Required,Timeout=1200)]
    
  • 當執行程式碼時,可能會收到某些未預期的例外狀況。若要收到有關這些例外狀況的詳細資訊,取消註解步驟 13 中的最後兩個程式行:
    Console::WriteLine("Error Message: {0}",e->Message);
    uncomment this line if you must get detailed error information

?考

如需詳細資訊請造訪下列 Microsoft 開發 o 人 h 員 ? 工 u 具 ? 網路 (MSDN) 網站]:
COM + 整合: 如何.NET 企業服務可以協助您建置分散式應用程式
服務的元件

屬性

文章編號: 815814 - 上次校閱: 2007年11月14日 - 版次: 3.2
這篇文章中的資訊適用於:
  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET 2003 Standard Edition
關鍵字:?
kbmt kbsqlclient kbcomplusqc kbcode kbhowtomaster kbhowto KB815814 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:815814
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com