方法 :Compensating Resource Manager (CRM) を作成する

コード例

CRM (Compensating Resource Manager) とは、非トランザクション オブジェクトを Microsoft 分散トランザクション コーディネータ (DTC: Distributed Transaction Coordinator) トランザクションに組み込むことができるようにする COM+ のサービスです。CRM は完全なリソース マネージャの機能を備えていませんが、トランザクションの最小性 (all-or-nothing の動作) と、復元ログを通じての永続性を提供します。

Compensating Resource Manager 作成するには

  1. EnterpriseServices および CompensatingResourceManager 名前空間をインポートします。

    Imports System.EnterpriseServices
    Imports System.EnterpriseServices.CompensatingResourceManager
    
    using System.EnterpriseServices;
    using System.EnterpriseServices.CompensatingResourceManager;
    
  2. CRM のアセンブリ サポートを有効にします。

    <assembly: ApplicationCrmEnabled>
    
    [assembly: ApplicationCrmEnabled]
    
  3. ServicedComponent クラスから派生する CRM Worker クラスを定義します。たとえば、次のコードは、ServicedComponent から直接派生する CRMWorker クラスを示しています。

    <Transaction> Public Class CRMWorker
          Inherits Servicedcomponent
    
    End Class
    
    [Transaction]
    public class CRMWorker:ServicedComponent
    {
    }
    
  4. Clerk オブジェクトを作成するパブリック メソッドを実装し、トランザクションをコミットまたは中止します。このメソッドは、Clerk オブジェクトを使用して CRM ログを更新する必要があります。たとえば、次のコードは、CRM ログを更新してトランザクションをコミットまたは中止するメソッド CRMMethod を示しています。

    Public Sub CRMMethod(filename As String, bCommit As Boolean)
         ' Create the clerk object.
         Dim myclerk As Clerk=New Clerk(GetType(CRMCompensator), _
                   "CRMCompensator", CompensatorOptions.AllPhases)
         myclerk.WriteLogRecord(filename)
         myclerk.ForceLog()
         If bCommit=true Then
             ContextUtil.SetComplete()
         Else
             ContextUtil.SetAbort()
         End If
    End Sub
    
    public void CRMMethod(string fileName, bool bCommit)
    {
          // Create clerk object.
          Clerk clerk = new Clerk(typeof(CRMCompensator), 
                                "CRMCompensator",
                                CompensatorOptions.AllPhases);
          clerk.WriteLogRecord(fileName);
          clerk.ForceLog();
          if (bCommit)
               ContextUtil.SetComplete();
          else
               ContextUtil.SetAbort();
          }
    
  5. Compensation クラスから派生するクラスを定義します。

    JustInTimeActivation()
    Public Class CRMCompensator
            Inherits Compensator
    End Class
    
    [JustInTimeActivation]
    public class CRMCompensator:Compensator
    {
    }
    
Noteメモ :

JustInTimeActivation 属性を compensator に適用する必要があります。そうしなければ、abort が 2 回呼び出されます。

  1. Compensator クラスのメンバである BeginPreparePrepareRecordEndPrepareBeginCommitCommitRecordEndCommitBeginAbortAbortRecord、および EndAbort をオーバーライドします。

  2. クライアント アプリケーションを作成して、CRM Worker コンポーネントおよび Compensator コンポーネントをテストします。

    1. System.EnterpriseServices などの必須名、および CRM Worker クラスおよび Compensator クラスを実装する名前空間をインポートします。

      Imports System
      Imports System.IO
      Imports System.EnterpriseServices
      Imports CrmServer
      Imports System.Runtime.InteropServices
      
      using System;
      using System.IO;
      using System.EnterpriseServices;
      using CrmServer;
      using System.Runtime.InteropServices;
      
    2. クラスを定義し Main メソッドを実装して、CRM Worker クラスのインスタンスを作成します。さらに、CRM Clerk オブジェクトを作成するメソッドを呼び出します。たとえば、次のコードでは、CRMWorker タイプのオブジェクトを作成し CRMMethod メソッドを呼び出して、CRM Clerk オブジェクトを作成します。

      Public Class CRM
          Public Shared Sub Main()                        
             dim logfilename As String = "crm.log"
             Console.WriteLine("Creating a managed CRM worker"+ _ 
                                                   "object...")
             dim crmworker As CRMWorker = new CRMWorker()
             Console.WriteLine("Demonstrating a worker commit...")
             crmworker.CRMMethod(logfilename, True)
             Console.WriteLine("Demonstrating a worker abort...")
             crmworker.CRMMethod(logfilename, False)
             Console.WriteLine("DONE!")
          End Sub
      End Class
      
      class CRM
      {
          public static int Main()
          { 
             string logfilename = "crm.log";
             Console.WriteLine("Creating a managed CRM worker 
                                                object...");
             CRMWorker crmworker = new CRMWorker();
             Console.WriteLine("Demonstrating a worker commit...");
             crmworker.CRMMethod(logfilename, true);
             Console.WriteLine("Demonstrating a worker abort...");
             crmworker.CRMMethod(logfilename, false);
             Console.WriteLine("DONE!");
             return 0;   
          }
      }
      
  3. 強力なキーを生成して、次の例をコンパイルします。

    sn –k crm.key
    vbc /t:library /r:System.EnterpriseServices.dll crm.vb
    vbc /r:crm.dll /r:System.EnterpriseServices.dll crmclient.vb
    
    sn –k crm.key
    csc /t:library /r:System.EnterpriseServices.dll crm.cs
    csc /r:crm.dll crmclient.cs
    

Imports System
Imports System.IO
Imports System.Reflection
Imports System.EnterpriseServices
Imports System.EnterpriseServices.CompensatingResourceManager

<assembly: ApplicationActivation(ActivationOption.Server)>
<assembly: ApplicationCrmEnabled>
<assembly: AssemblyKeyFile("crm.key")>

Namespace CrmServer
' Create a Worker class.
<Transaction> Public Class CRMWorker
    Inherits Servicedcomponent
          Public Sub CRMMethod(filename As String, bCommit As Boolean)
              ' Create the clerk object.
              Dim myclerk As Clerk=New Clerk(GetType(CRMCompensator), _ 
                        "CRMCompensator", CompensatorOptions.AllPhases)
              myclerk.WriteLogRecord(filename)
              myclerk.ForceLog()
              If bCommit=true Then
                    ContextUtil.SetComplete()
              Else
                    ContextUtil.SetAbort()
              End If
        End Sub
    End Class

    ' Create a class derived from the Compensator class.
    JustInTimeActivation()
    Public Class CRMCompensator
      Inherits Compensator
            Dim bBeginPrepareCalled As Boolean = False
            Dim bPrepareRecordCalled As Boolean = False
            Dim bBeginCommitCalled As Boolean = False
            Dim bCommitRecordCalled As Boolean = False
            Dim bBeginAbortCalled As Boolean = False
            Dim bAbortRecordCalled As Boolean = False
            Dim _filename as String

            Public Overrides Sub BeginPrepare()
                  bBeginPrepareCalled = True
            End Sub

            Public Overrides Function PrepareRecord(rec As LogRecord) _
                                                           As Boolean
                  dim o as Object = rec.Record
                  _fileName = o.ToString()
                  bPrepareRecordCalled = True
                  Return False
            End Function

            Public Overrides Function EndPrepare() As Boolean
                  if not bBeginPrepareCalled then Return False   

                  if not bPrepareRecordCalled then Return False
                  if _fileName="" then Return False
                  ' This is a Prepare Phase success.
                  Return True
            End Function

            Public Overrides Sub BeginCommit(fRecovery As Boolean)
                  bBeginCommitCalled = True
            End Sub

            Public Overrides Function CommitRecord(rec As LogRecord) _
                                                          As Boolean
                  bCommitRecordCalled = True
                  Return True
            End Function

            Public Overrides Sub EndCommit()
                  if not bBeginCommitCalled then Return 
                  if not bCommitRecordCalled then Return 
                  if _fileName="" then Return 
                  ' This is a Commit Phase success.
            End Sub

            Public Overrides Sub BeginAbort(fRecovery As Boolean)
                  bBeginAbortCalled = True
            End Sub
            
            Public Overrides Function AbortRecord(rec As LogRecord) _
                                                          As Boolean
                  bAbortRecordCalled = True
                  dim o as Object = rec.Record
                  _fileName = o.ToString()
                  Return True
            End Function

            Public Overrides Sub EndAbort()
                  if not bBeginAbortCalled then Return 
                  if not bAbortRecordCalled then Return 
                  if _fileName="" then Return
                  ' This is an Abort Phase success.
            End Sub
      End Class
End Namespace
      
      
using System;
using System.IO;
using System.Reflection;
using System.EnterpriseServices;
using System.EnterpriseServices.CompensatingResourceManager;

[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationCrmEnabled]
[assembly: AssemblyKeyFile("crm.key")]

namespace CrmServer 
{
      [Transaction]
      // Create a Worker class.
      public class CRMWorker:ServicedComponent
      {
            public void CRMMethod(string fileName, bool bCommit)
            {
                  // Create clerk object.
                  Clerk clerk = new Clerk(typeof(CRMCompensator),
                       "CRMCompensator", CompensatorOptions.AllPhases);
                  clerk.WriteLogRecord(fileName);
                  clerk.ForceLog();
                  if (bCommit)
                        ContextUtil.SetComplete();
                  else
                        ContextUtil.SetAbort();
            }
      
      }
      // Create class derived from Compensator class.
      [JustInTimeActivation]
      public class CRMCompensator:Compensator
      {
            bool bBeginPrepareCalled = false;
            bool bPrepareRecordCalled = false;
            bool bBeginCommitCalled = false;
            bool bCommitRecordCalled = false;
            bool bBeginAbortCalled = false;
            bool bAbortRecordCalled = false;
      
            String _fileName;
      
            public override void BeginPrepare()
            {
                  bBeginPrepareCalled = true;
            }
      
            public override bool PrepareRecord(LogRecord rec)
            {
                  Object o = rec.Record;
                  _fileName = o.ToString();
                  bPrepareRecordCalled = true;
                  return false;
            }
      
            public override bool EndPrepare()
            {
                  if (!bBeginPrepareCalled)
                  {return false;}   
                  if (!bPrepareRecordCalled)
                  {return false;}   
                  if (_fileName==null)
                  {return false;}
                  // This is a Prepare Phase success.
                  return true;
            }
      
            public override void BeginCommit(bool fRecovery)
            {
                  bBeginCommitCalled = true;
            }
      
            public override bool CommitRecord(LogRecord rec)
            {
                  bCommitRecordCalled = true;
                  return true;
            }
      
            public override void EndCommit()
            {
                  if (!bBeginCommitCalled)
                  {return;}   
                  if (!bCommitRecordCalled)
                  {return;}
                  if (_fileName==null)
                  {return;}
                  // This is a Commit Phase success.
            }
      
            public override void BeginAbort(bool fRecovery)
            {
                  bBeginAbortCalled = true;
            }
      
            public override bool AbortRecord(LogRecord rec)
            {
                  bAbortRecordCalled = true;
                  Object o = rec.Record;
                  _fileName = o.ToString();
                  return true;
            }
      
            public override void EndAbort()
            {
                  if (!bBeginAbortCalled)
                  {return;}   
                  if (!bAbortRecordCalled)
                  {return;}               
                  if (_fileName==null)
                  {return;}
                  // This is an Abort Phase success.
            }
      
      }

}

関連項目

参照

System.EnterpriseServices Namespace

概念

利用可能な COM+ サービスの概要

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.