共用方式為


HOW TO:建立 Compensating Resource Manager (CRM)

程式碼範例

Compensating Resource Manager (CRM) 是 COM+ 所提供的服務,它可讓您在 Microsoft Distributed Transaction Coordinator (DTC) 交易中包含非交易性物件。雖然 CRM 並未提供完整資源管理員的功能,不過它會透過復原記錄檔來提供交易的單元性 (全部或全無的行為特性) 和持續性。

建立 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 背景工作類別。例如,以下程式碼顯示直接衍生自 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),否則中止會被呼叫兩次。

  1. 覆寫 Compensator 類別的 BeginPreparePrepareRecordEndPrepareBeginCommitCommitRecordEndCommitBeginAbortAbortRecordEndAbort 等成員。

  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 背景工作類別的執行個體,並呼叫建立 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.