.NET Framework 開発者ガイド
方法 : コンペンセート リソース マネージャ (CRM) を作成する

コード例

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

補正リソース マネージャを作成するには

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

    Visual Basic
    Imports System.EnterpriseServices
    Imports System.EnterpriseServices.CompensatingResourceManager

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

    Visual Basic
    <assembly: ApplicationCrmEnabled>

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

    Visual Basic
    <Transaction> Public Class CRMWorker
          Inherits Servicedcomponent
                
    End Class

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

    Visual Basic
    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

    C#
    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 クラスから派生するクラスを定義します。

    Visual Basic
    JustInTimeActivation()
    Public Class CRMCompensator
            Inherits Compensator
    End Class

    C#
    [JustInTimeActivation]
    public class CRMCompensator:Compensator
    {
    }
Noteメモ :

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

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

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

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

      Visual Basic
      Imports System
      Imports System.IO
      Imports System.EnterpriseServices
      Imports CrmServer
      Imports System.Runtime.InteropServices

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

      Visual Basic
      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

      C#
      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. 強力なキーを生成して、次の例をコンパイルします。

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

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

使用例

Visual Basic
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
      
      
C#
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.
            }
      
      }

}

参照

タグ :


Page view tracker