Share via


Cómo crear un administrador de compensación de recursos (CRM)

Ejemplo de código

Un administrador de compensación de recursos (CRM) es un servicio proporcionado por COM+ que permite incluir objetos no transaccionales en las transacciones del Coordinador de transacciones distribuidas de Microsoft (DTC). Aunque los CRM no ofrecen las funcionalidades de un administrador de recursos completo, proporcionan la atomicidad transaccional (comportamiento todo o nada) y la durabilidad por medio del registro de recuperación.

Para crear un administrador de compensación de recursos

  1. Importe los espacios de nombres EnterpriseServices y CompensatingResourceManager.

    Imports System.EnterpriseServices
    Imports System.EnterpriseServices.CompensatingResourceManager
    
    using System.EnterpriseServices;
    using System.EnterpriseServices.CompensatingResourceManager;
    
  2. Habilite la compatibilidad con CRM para el ensamblado.

    <assembly: ApplicationCrmEnabled>
    
    [assembly: ApplicationCrmEnabled]
    
  3. Defina una clase CRM Worker que se derive de la clase ServicedComponent. Por ejemplo, el código siguiente muestra una clase CRMWorker que se deriva directamente de ServicedComponent.

    <Transaction> Public Class CRMWorker
          Inherits Servicedcomponent
    
    End Class
    
    [Transaction]
    public class CRMWorker:ServicedComponent
    {
    }
    
  4. Implemente un método público que cree un objeto Clerk y confirme o anule la transacción. El método debe actualizar el registro de CRM mediante el uso del objeto Clerk. Por ejemplo, el siguiente código muestra un método CRMMethod que actualiza el registro CRM y confirma o anule la transacción.

    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. Defina una clase que se derive de la clase Compensation.

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

Debe aplicar el atributo JustInTimeActivation al compensador; en caso contrario, se llama dos veces a la cancelación.

  1. Anule los miembros BeginPrepare, PrepareRecord, EndPrepare, BeginCommit, CommitRecord, EndCommit, BeginAbort, AbortRecord y EndAbort de la clase Compensator.

  2. Cree una aplicación cliente para probar los componentes CRM Worker y Compensator.

    1. Importe los nombres necesarios, como System.EnterpriseServices y el espacio de nombres que implementa las clases CRM Worker y 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. Defina una clase e implemente el método Main para crear una instancia de la clase CRM Worker y llame al método que crea el objeto Clerk de CRM. Por ejemplo, el siguiente código crea un objeto del tipo CRMWorker y llama al método CRMMethod para crear el objeto Clerk de CRM.

      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. Genere una clave segura y compile el siguiente ejemplo.

    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
    

Ejemplo

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.
            }
      
      }

}

Consulte también

Referencia

System.EnterpriseServices Namespace

Conceptos

Resumen de los servicios COM+ disponibles

Copyright © 2007 Microsoft Corporation. Reservados todos los derechos.