Visual C# コンポーネントで COM+ トランザクションを使用する方法

文書翻訳 文書翻訳
文書番号: 816141 - 対象製品
すべて展開する | すべて折りたたむ

目次

概要

この資料では、Visual C# クラスで COM+ (コンポーネント サービス) トランザクションを使用する方法について手順を追って説明します。一連のデータベース操作は 1 つの単位と見なされます。すべての操作が成功すれば、トランザクションは成功しますが、操作が 1 つでも失敗すると、トランザクション全体が失敗します。後者の場合、実行したデータベース操作は基になるデータベースにポストされません。

必要条件

必要なハードウェア、ソフトウェア、ネットワーク インフラストラクチャ、技術と知識、および Service Pack は次のとおりです。
  • Microsoft Windows 2000 Server SP1
  • Microsoft Internet Information Server (IIS) 4.0 またはインターネット インフォメーション サービス 5.0 以降
  • Microsoft Internet Explorer 5.0、5.5、または 6.0
この資料は、以下について詳しい知識のあるユーザーを対象としています。
  • トランザクションの概念と処理
  • COM+ (コンポーネント サービス)

COM+ トランザクション サービス

トランザクション処理は、Microsoft .NET Framework の System.EnterpriseServices 名前空間を使用して実装できます。COM+ トランザクション サービスにアクセスするには、次の手順に従ってクラスを作成します。
  1. Visual Studio .NET または Visual Studio 2005 を起動します。
  2. [ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
  3. [プロジェクトの種類] ボックスの一覧の [Visual C# プロジェクト] をクリックし、[テンプレート] ボックスの一覧の [クラス ライブラリ] をクリックします。[プロジェクト名] ボックスに prjEnterprise と入力し、[OK] をクリックします。

    : Visual Studio 2005 では、[プロジェクトの種類] ボックスの一覧の [Visual C# プロジェクト] をクリックし、[テンプレート] ボックスの一覧の [クラス ライブラリ] をクリックします。プロジェクト名として prjEnterprise を指定します。
  4. デフォルトで Class1 が作成されます。
  5. ソリューション エクスプローラで、[参照設定] を右クリックし、[参照の追加] をクリックします。
  6. [参照の追加] ダイアログ ボックスが表示されます。[.NET] タブの [コンポーネント名] の下にある [System.EnterpriseServices] をダブルクリックします。
  7. [選択されたコンポーネント] の下に System.EnterpriseServices が表示されていることを確認します。[OK] をクリックします。
  8. Class1.cs ファイルの先頭に、次のコードを追加します。
    using System.EnterpriseServices;
    using System.Data.SqlClient;
  9. Class1.cs ファイルに clsES という名前の新しいクラスを追加します。
  10. COM+ トランザクション サービスを使用するには、クラス (clsES) が次のように ServicedComponent から機能を継承する必要があります。
    public class clsES : ServicedComponent
  11. Transaction 属性を使用して、次のようにクラスのトランザクション サポートのレベルを指定します。
    [Transaction(TransactionOption.Required)]public class clsES : ServicedComponent
  12. clsES クラスに 4 つの入力整数パラメータを受け取るメソッドを作成し、dbAccess という名前を付けます。最初の 2 つのパラメータで商品 ID (ProductID) とその商品の受注数 (UnitsOnOrder) を入力します。次の 2 つのパラメータで商品 ID とその商品の在庫数 (UnitsInStock) を入力します。このメソッドは、指定したこれらの商品 ID に対して一連のデータベース操作を実行し、これらがトランザクションとして処理されます。
    void dbAccess(int pID1,int onOrder, int pID2, int inStock)
  13. dbAccess メソッドで、Northwind データベースの SQL 接続オブジェクトを作成し、接続を開きます。データベース操作は、次のデータベースを使用して行います。

    : 使用する SQL Server サーバーの値に合わせて、次の接続文字列パラメータを変更してください。
    SqlConnection Conn = new SqlConnection("user id=<username>;password=<strong password>;Initial Catalog=northwind;Data Source=2E124\\SQL;");
    				Conn.Open();
    
  14. try ブロックを設定し、データベース処理中に発生する例外を捕捉します。これらの例外をキャッチして、トランザクションを中断する必要があります。try ブロックには、データベース操作が 2 つ含まれます。操作ごとに、指定した商品 (Products) テーブル レコード内の異なるフィールドが更新されます。
     try { 
    
  15. 商品テーブルに対して最初の更新を実行します。最初の 2 つの入力パラメータで指定された値を使用して、ID が pID1 の商品について、UnitsOnOrder フィールドを onOrder 値に更新します。この SQL 更新の実行には、次の SQL コマンドを使用します。
    SqlCommand sqlCommand = new SqlCommand("UPDATE myProducts SET UnitsonOrder = " + onOrder + " WHERE productID = " + pID1, Conn);
    				sqlCommand.ExecuteNonQuery();
  16. 商品テーブルに対してもう一度更新を実行します。3 番目および 4 番目の入力パラメータで指定された値を使用して、ID が pID2 の商品について、UnitsInStock フィールドを inStock 値に更新します。この SQL 更新の実行には、次の SQL コマンドを使用します。
    sqlCommand.CommandText = "UPDATE myProducts SET UnitsinStock = " + inStock + " WHERE productID = " + pID2;
    				sqlCommand.ExecuteNonQuery();
    
  17. これらの更新は COM+ トランザクションの一部であるため、1 つの単位としてコミットされます。System.EnterpriseServices 名前空間に含まれる contextUtil クラスの setComplete メソッドは、エラーがスローされなかった場合に、トランザクション (この場合は 2 回の更新) をコミットするために使用されます。
    ContextUtil.SetComplete();
  18. Northwind データベースへの接続を閉じます。
    Conn.Close();
    }
  19. トランザクション全体を中断できるように、SQL コマンドの実行中に発生する例外をキャッチする必要があります。
    catch(Exception e){ 
  20. System.EnterpriseServices 名前空間に含まれる contextUtil クラスの setAbort メソッドを使用して、トランザクション全体を中断します。最初の更新が成功し、2 回目の更新が失敗すると、どちらの更新も商品テーブルにポストされません。キャッチされた例外は呼び出し元にスローされ、トランザクションが失敗したことが通知されます。
    ContextUtil.SetAbort();
    				throw e;
    }
  21. このコンポーネントが適切に機能するには、コンポーネントに厳密な名前を付ける必要があります。厳密な名前を作成し、厳密な名前を使用してアセンブリを署名します。これを行うには、次の手順を実行します。
    1. Visual Studio .NET のコマンド プロンプトで sn.exe -k snEnterprise.snk と入力し、キー ファイルを作成します。厳密な名前を使用してアセンブリを署名する方法の詳細については、.NET Framework SDK ドキュメントを参照してください。
    2. snEnterprise.snk をプロジェクト フォルダにコピーします。
    3. AssemblyInfo.cs で、他のアセンブリ属性のステートメントの前または後に、次のコード行を追加します。
      [assembly: AssemblyKeyFileAttribute("..\\..\\snEnterprise.snk")]		
    4. プロジェクトを保存してビルドします。

完全なコード リスト



: 使用する SQL Server サーバーの値に合わせて、次の接続文字列パラメータを変更してください。
using System;
using System.Data;
using System.Data.SqlTypes;
using System.Data.Common;
using System.EnterpriseServices;
using System.Data.SqlClient;

namespace prjEnterprise
{
	
	[Transaction(TransactionOption.Required)]public class clsES:ServicedComponent
	{
		public SqlConnection Conn;

		public void dbAccess(int pID1, int onOrder, int pID2, int inStock)
		{
			try
			{			
				SqlConnection Conn = new SqlConnection("user id=<username>;password=<strong password>;Initial Catalog=northwind;Data Source=2E124\\SQL;");
				Conn.Open();
				
SqlCommand sqlCommand = new SqlCommand("UPDATE myProducts SET UnitsonOrder = " + onOrder + " WHERE productID = " + pID1, Conn);
				sqlCommand.ExecuteNonQuery();
				
				sqlCommand.CommandText = "UPDATE myProducts SET UnitsinStock = " + inStock + " WHERE productID = " + pID2;
				sqlCommand.ExecuteNonQuery();

				ContextUtil.SetComplete();
				Conn.Close();
			}
			catch(Exception e)
			{
				ContextUtil.SetAbort();
			
				throw e;
			}
			finally
			{

			}
		}
	}	
}

動作の検証

コードをテストするには、clsES プロジェクトを使用するコンソール アプリケーションを作成します。トランザクションが成功し、指定した商品の UnitsOnOrder フィールドと UnitsInStock フィールドが更新される場合と、指定した製品 ID が商品テーブルに存在しないため、指定した製品の UnitsOnOrder フィールドの更新が成功し、商品の UnitsInStock フィールドの更新が失敗する場合があります。後者の場合、トランザクションは失敗し、トランザクションは無視されます。
  1. Visual Studio .NET または Visual Studio 2005 で、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
  2. [プロジェクトの種類] ボックスの一覧の [Visual C# プロジェクト] をクリックし、[テンプレート] ボックスの一覧の [コンソール アプリケーション] をクリックします。

    : Visual Studio 2005 では、[プロジェクトの種類] ボックスの一覧の [Visual C# プロジェクト] をクリックし、[テンプレート] ボックスの一覧の [コンソール アプリケーション] をクリックします。
  3. [プロジェクト名] ボックスに testES と入力し、[ソリューションに追加] をクリックします。
  4. [OK] をクリックして、このプロジェクトをソリューションに追加します。
  5. clsES をテストするには、testES に参照を追加する必要があります。ソリューション エクスプローラで、追加された [testES] の下の [参照設定] を右クリックし、[参照の追加] をクリックします。
  6. [参照の追加] ダイアログ ボックスが表示されます。[プロジェクト] タブで [prjEnterprise] をダブルクリックします。
  7. [選択されたコンポーネント] の下に参照が表示されます。[OK] をクリックして、この参照をプロジェクトに追加します。
  8. System.EnterpriseServices ライブラリへの参照をプロジェクトに追加します。ソリューション エクスプローラで、[参照設定] を右クリックし、[参照の追加] をクリックします。
  9. [参照の追加] ダイアログ ボックスが表示されます。[.NET] タブの [コンポーネント名] の下にある [System.EnterpriseServices] をダブルクリックします。
  10. [選択されたコンポーネント] の下に System.EnterpriseServices が表示されていることを確認します。[OK] をクリックします。
  11. ソリューション エクスプローラで [testES] を右クリックし、[スタートアップ プロジェクトに設定] をクリックします。
  12. Class1 クラスの Main 関数に、次のソース コードを貼り付けます。
    	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");
    				}
  13. F5 キーを押してプログラムをテストします。

    手順 12. のコードでは、dbAccess への最初の呼び出しは成功します。Product 1 および Product 2 は商品テーブルに含まれています。Product 1 の UnitsOnOrder フィールドが 777 に更新され、Product 2 の UnitsInStock フィールドが 888 に更新されます。このトランザクションが成功したため、出力ウィンドウに次のメッセージが表示されます。
    TRANSACTION ONE - SUCCESS


    dbAccess への 2 回目の呼び出しは失敗します。そのため、dbAccess の商品テーブルの更新ステートメントはデータベースにポストされません。Product 1 の UnitsOnOrder フィールドを 5 に更新できますが、Product 2 では UnitsInStock フィールドを -20 に設定できません。商品テーブルの定義の制約により、inStock では負の数値を使用できません。

    したがって、dbAccess への呼び出しが失敗し、トランザクション全体が失敗します。Products テーブルは、dbAccess への呼び出し前の状態から変更されません。dbAccess からのトランザクション失敗の通知が catch ステートメントによって処理され、出力ウィンドウに次のエラー メッセージが表示されます。
    TRANSACTION FAILURE
  14. SQL Server のエンタープライズ マネージャを使用して、Northwind の Products テーブルの内容を検証します。Product 1 を確認すると、UnitsOnOrder フィールドが 777 となっています。Product 2 を確認すると、UnitsInStock フィールドが 888 となっています。このことから、これらのフィールドを別の値に更新するための 2 回目の dbAccess の呼び出しが失敗したことがわかります。

トラブルシューティング

  • COM+ サービスを使用するプロジェクトに厳密な名前が付いていることを確認します。
  • COM+ サービスを使用するクラスは、サービス コンポーネントから継承する必要があります。サービス コンポーネントは、System.EnterpriseServices 名前空間にあります。
  • デバッグ時、トランザクションがコミットまたは中断される前に、トランザクションがタイムアウトすることがあります。タイムアウトを回避するには、トランザクション属性のタイムアウト プロパティを使用します。次の例では、関連するメソッドがタイムアウトせずにトランザクションを完了するための時間は 1,200 秒です。
    [Transaction(TransactionOption.Required,timeout:=1200)]

関連情報

詳細については、次の MSDN (Microsoft Developer Network) Web サイトを参照してください。
COM+ Integration: How .NET Enterprise Services Can Help You Build Distributed Applications
http://msdn.microsoft.com/msdnmag/issues/01/10/complus/default.aspx
サービス コンポーネント
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/f_and_m/html/vxconInterop.asp

プロパティ

文書番号: 816141 - 最終更新日: 2006年10月4日 - リビジョン: 3.2
この資料は以下の製品について記述したものです。
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft Visual C# 2005
キーワード:?
kbcomplusobj kbsqlprog kbsqlclient kbdatabase kbhowtomaster KB816141
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

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