Verfahrensweise: Erstellen eines kompensierenden Ressourcen-Managers (CRM)
Codebeispiel
Ein kompensierender Ressourcen-Manager (Compensating Resource Manager, CRM) ist ein von COM+ bereitgestellter Dienst, mit dem Sie nicht transaktionale Objekte in DTC-Transaktionen (Microsoft Distributed Transaction Coordinator) aufnehmen können. Obwohl CRMs nicht über die Fähigkeiten eines vollständigen Ressourcen-Managers verfügen, kann durch sie mithilfe des Wiederherstellungsprotokolls die Unteilbarkeit (Verhalten nach dem Prinzip "alles oder nichts") und Dauerhaftigkeit von Transaktionen gewährleistet werden.
So erstellen Sie einen kompensierenden Ressourcen-Manager
Importieren Sie die Namespaces "EnterpriseServices" und "CompensatingResourceManager".
Imports System.EnterpriseServices Imports System.EnterpriseServices.CompensatingResourceManager
using System.EnterpriseServices; using System.EnterpriseServices.CompensatingResourceManager;
Aktivieren Sie die CRM-Unterstützung für die Assembly.
<assembly: ApplicationCrmEnabled>
[assembly: ApplicationCrmEnabled]
Definieren Sie eine CRM-Workerklasse, die von der ServicedComponent-Klasse abgeleitet wird. Der folgende Code zeigt beispielsweise eine Klasse
CRMWorker
, die direkt von der ServicedComponent-Klasse abgeleitet wird.<Transaction> Public Class CRMWorker Inherits Servicedcomponent End Class
[Transaction] public class CRMWorker:ServicedComponent { }
Implementieren Sie eine öffentliche Methode, die ein Clerk-Objekt erstellt und den Commit der Transaktion durchführt oder sie abbricht. Die Methode muss das CRM-Protokoll mithilfe des Clerk-Objekts aktualisieren. Der folgende Code beispielsweise zeigt eine Methode
CRMMethod
, die das CRM-Protokoll aktualisiert und den Commit der Transaktion durchführt oder sie abbricht.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(); }
Definieren Sie eine Klasse, die von der Compensator-Klasse abgeleitet wird.
JustInTimeActivation() Public Class CRMCompensator Inherits Compensator End Class
[JustInTimeActivation] public class CRMCompensator:Compensator { }
Hinweis: |
---|
Sie müssen das |
Setzen Sie die
BeginPrepare
-,PrepareRecord
-,EndPrepare
-,BeginCommit
-,CommitRecord
-,EndCommit
-,BeginAbort
-,AbortRecord
- undEndAbort
-Member der Compensator-Klasse außer Kraft.Erstellen Sie eine Clientanwendung zum Testen der CRM-Worker- und -Kompensatorkomponenten.
Importieren Sie die erforderlichen Namen, wie z. B. System.EnterpriseServices und den Namespace, der die CRM-Worker- und -Kompensatorklassen implementiert.
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;
Definieren Sie eine Klasse, und implementieren Sie die Main-Methode, um eine Instanz der CRM-Workerklasse, und rufen Sie die Methode auf, die das CRM-Clerk-Objekt erstellt. Der folgende Code erstellt beispielsweise ein Objekt vom Typ
CRMWorker
und ruft die MethodeCRMMethod
auf, um das CRM-Clerk-Objekt zu erstellen.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; } }
Generieren Sie einen starken Schlüssel, und kompilieren Sie folgendes Beispiel.
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
Beispiel
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.
}
}
}
Siehe auch
Referenz
System.EnterpriseServices Namespace
Konzepte
Zusammenfassung der verfügbaren COM+-Dienste
Copyright © 2007 by Microsoft Corporation. Alle Rechte vorbehalten.