Rejestrowanie zasobów jako uczestników transakcji

Każdy zasób Udział w transakcji jest zarządzane przez Menedżera zasobów, których działania są koordynowany przez Menedżera transakcji. Koordynacja jest wykonywane za pośrednictwem powiadomienia do subskrybentów, którzy mają zarejestrowane w transakcji za pośrednictwem Menedżera transakcji.

W tym temacie opisano, jak zasób (lub wiele zasobów) można zarejestrować w transakcji, a także różne typy rejestracji. W temacie Zatwierdzanie transakcji w jednej fazie i wielofazowej opisano sposób koordynowania zobowiązania transakcji między zasobami z listy.

Rejestrowanie zasobów w transakcji

Aby zasób, aby uczestniczyć w transakcji należy zarejestrować w transakcji. Klasa Transaction definiuje zestaw metod, których nazwy zaczynają się od Enlist , które zapewniają tę funkcję. Różne metody rejestracji odpowiadają różnym typom rejestracji, które może mieć menedżer zasobów. W szczególności użyj EnlistVolatile metody dla lotnych zasoby i EnlistDurable metody dla trwałego zasobów. Trwałość (lub odwrotnie niestabilności ich) zasobu menedżera odwołuje się do tego, czy Menedżera zasobów obsługuje odzyskiwanie po awarii. Jeśli Menedżera zasobów obsługuje odzyskiwanie po awarii, utrzymuje danych do trwałego magazynu podczas fazy 1. (przygotowanie) tak, aby w przypadku awarii Menedżera zasobów, można ponownie zarejestrować transakcji po odzyskiwania i wykonać właściwe działania w oparciu o powiadomienia otrzymane z Menedżer transakcji. Ogólnie rzecz biorąc, menedżerowie zasobów nietrwałych zarządzają nietrwałymi zasobami, takimi jak struktura danych w pamięci (na przykład tabela transacted-hashtable w pamięci) i trwałe menedżery zasobów zarządzają zasobami, które mają bardziej trwały magazyn zapasowy (na przykład bazę danych, której magazyn zapasowy jest dyskiem).

Dla uproszczenia, po podjęciu decyzji, czy użyć EnlistDurable metody lub EnlistVolatile na podstawie obsługi trwałości zasobu, należy zarejestrować zasób, aby wziąć udział w dwufazowym zatwierdzaniu (2PC), implementując IEnlistmentNotification interfejs dla menedżera zasobów. Aby uzyskać więcej informacji na temat 2PC, zobacz Zatwierdzanie transakcji w jednej fazie i wielofazowej.

Jeden uczestnik może zarejestrować się do więcej niż jednego z tych protokołów przez wywołanie EnlistDurable i EnlistVolatile wiele razy.

Trwałej rejestracji

EnlistDurable Metody są używane do zarejestrować Menedżera zasobów uczestniczący w transakcji jako trwałe zasobu. Oczekuje się, że jeśli trwały menedżer zasobów zostanie wyłączony w trakcie transakcji, może wykonać odzyskiwanie po powrocie do trybu online przez ponowne utworzenie listy (przy użyciu Reenlist metody) we wszystkich transakcjach, w których był uczestnikiem i nie zakończył fazy 2, i wywołaj RecoveryComplete po zakończeniu przetwarzania odzyskiwania. Aby uzyskać więcej informacji na temat odzyskiwania, zobacz Wykonywanie odzyskiwania.

EnlistDurable Podjąć wszystkie metody Guid obiektu jako jego pierwszym parametrem. Guid Jest używana przez Menedżera transakcji do skojarzenia trwałej rejestracji z menedżerem określonego zasobu. Jako takie, należy bezwzględnie Menedżera zasobów stale używany w taki sam Guid do identyfikacji nawet przez inny zasób menedżerów przy ponownym uruchomieniu, w przeciwnym razie odzyskiwania może zakończyć się niepowodzeniem.

Drugi parametr EnlistDurable metody jest odwołaniem do obiektu, który menedżer zasobów implementuje w celu odbierania powiadomień transakcji. Przeciążenie, którego używasz informuje menedżera transakcji, czy Menedżera zasobów obsługuje optymalizacji jednego etapu zatwierdzania (SPC). W większości przypadków należy zaimplementować IEnlistmentNotification interfejs do udziału w zatwierdzaniu dwufazowym (2PC). Jeśli jednak chcesz zoptymalizować proces zatwierdzania, możesz rozważyć zaimplementowanie interfejsu ISinglePhaseNotification dla usługi SPC. Aby uzyskać więcej informacji na temat spC, zobacz Commiting a Transaction in Single-Phase and Multi-Phase and Optimization using Single Phase Commit and Promotable Single Phase Notification (Zatwierdzanie transakcji w pojedynczej fazie i optymalizacji przy użyciu jednofazowego zatwierdzania jednofazowego i promotable jednofazowego powiadomienia).

Trzeci parametr jest EnlistmentOptions wyliczenia, którego wartość może być None lub EnlistDuringPrepareRequired. Jeśli wartość jest równa EnlistDuringPrepareRequired, rejestracja może zarejestrować menedżerów dodatkowych zasobów po otrzymaniu zawiadomienia Prepare z menedżerem transakcji. Należy jednak pamiętać, że tego typu rejestracji jest nieodpowiedni dla pojedynczego Zatwierdź faza optymalizacji.

Rejestracja lotnych

Uczestnicy zarządzania zasobami lotnych, takich jak pamięci podręcznej należy zarejestrować przy użyciu EnlistVolatile metody. Takie obiekty mogą nie można uzyskać wynik transakcji lub odzyskać stan każdej transakcji, które uczestniczą w po awarii systemu.

W sposób opisany wcześniej, Menedżera zasobów spowodowałoby lotnych rejestracji, jeśli zarządza w pamięci, lotnych zasobu. Jedną z zalet za pomocą EnlistVolatile jest, że nie wymusza niepotrzebne eskalacji transakcji. Aby uzyskać więcej informacji na temat eskalacji transakcji, zobacz Temat Eskalacja zarządzania transakcjami. Rejestrowanie zmienności oznacza zarówno różnicę w sposobie obsługi rejestracji przez menedżera transakcji, jak i oczekiwane przez menedżera zasobów przez menedżera transakcji. Jest to spowodowane Menedżera zasobów lotnych nie wykonuje odzyskiwania. EnlistVolatile Metody nie przyjmują Guid parametru, ponieważ Menedżer zasobów lotnych nie wykonuje odzyskiwania i nie może wywołać Reenlist metodę, którą Guid.

Podobnie jak w przypadku trwałych rejestracji, niezależnie od metody przeciążenie umożliwia rejestrowanie oznacza menedżera transakcji czy Menedżera zasobów obsługuje optymalizacji Zatwierdź jednego etapu. Ponieważ Menedżer zasobów lotnych nie może wykonać odzyskiwania, żadne informacje odzyskiwania jest przeznaczony dla lotnych rejestracji w fazie Prepare. Dlatego wywołanie RecoveryInformation metoda nie powoduje InvalidOperationException.

W poniższym przykładzie pokazano, jak zarejestrować taki obiekt jako uczestnik transakcji przy użyciu EnlistVolatile metody .

static void Main(string[] args)
{
    try
    {
        using (TransactionScope scope = new TransactionScope())
        {

            //Create an enlistment object
            myEnlistmentClass myEnlistment = new myEnlistmentClass();

            //Enlist on the current transaction with the enlistment object
            Transaction.Current.EnlistVolatile(myEnlistment, EnlistmentOptions.None);

            //Perform transactional work here.

            //Call complete on the TransactionScope based on console input
                            ConsoleKeyInfo c;
            while(true)
                            {
                Console.Write("Complete the transaction scope? [Y|N] ");
                c = Console.ReadKey();
                Console.WriteLine();

                                    if ((c.KeyChar == 'Y') || (c.KeyChar == 'y'))
                {
                    scope.Complete();
                    break;
                }
                else if ((c.KeyChar == 'N') || (c.KeyChar == 'n'))
                {
                    break;
                }
            }
        }
    }
    catch (System.Transactions.TransactionException ex)
    {
        Console.WriteLine(ex);
    }
    catch
    {
        Console.WriteLine("Cannot complete transaction");
        throw;
    }
}

class myEnlistmentClass : IEnlistmentNotification
{
    public void Prepare(PreparingEnlistment preparingEnlistment)
    {
        Console.WriteLine("Prepare notification received");

        //Perform transactional work

        //If work finished correctly, reply prepared
        preparingEnlistment.Prepared();

        // otherwise, do a ForceRollback
        preparingEnlistment.ForceRollback();
    }

    public void Commit(Enlistment enlistment)
    {
        Console.WriteLine("Commit notification received");

        //Do any work necessary when commit notification is received

        //Declare done on the enlistment
        enlistment.Done();
    }

    public void Rollback(Enlistment enlistment)
    {
        Console.WriteLine("Rollback notification received");

        //Do any work necessary when rollback notification is received

        //Declare done on the enlistment
        enlistment.Done();
    }

    public void InDoubt(Enlistment enlistment)
    {
        Console.WriteLine("In doubt notification received");

        //Do any work necessary when in doubt notification is received

        //Declare done on the enlistment
        enlistment.Done();
    }
}
    Public Shared Sub Main()
        Try
            Using scope As TransactionScope = New TransactionScope()

                'Create an enlistment object
                Dim myEnlistmentClass As New EnlistmentClass

                'Enlist on the current transaction with the enlistment object
                Transaction.Current.EnlistVolatile(myEnlistmentClass, EnlistmentOptions.None)

                'Perform transactional work here.

                'Call complete on the TransactionScope based on console input
                Dim c As ConsoleKeyInfo
                While (True)
                    Console.Write("Complete the transaction scope? [Y|N] ")
                    c = Console.ReadKey()
                    Console.WriteLine()
                    If (c.KeyChar = "Y") Or (c.KeyChar = "y") Then
                        scope.Complete()
                        Exit While
                    ElseIf ((c.KeyChar = "N") Or (c.KeyChar = "n")) Then
                        Exit While
                    End If
                End While
            End Using
        Catch ex As TransactionException
            Console.WriteLine(ex)
        Catch
            Console.WriteLine("Cannot complete transaction")
            Throw
        End Try
    End Sub
End Class

Public Class EnlistmentClass
    Implements IEnlistmentNotification

    Public Sub Prepare(ByVal myPreparingEnlistment As PreparingEnlistment) Implements System.Transactions.IEnlistmentNotification.Prepare
        Console.WriteLine("Prepare notification received")

        'Perform transactional work

        'If work finished correctly, reply with prepared
        myPreparingEnlistment.Prepared()
    End Sub

    Public Sub Commit(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Commit
        Console.WriteLine("Commit notification received")

        'Do any work necessary when commit notification is received

        'Declare done on the enlistment
        myEnlistment.Done()
    End Sub

    Public Sub Rollback(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Rollback
        Console.WriteLine("Rollback notification received")

        'Do any work necessary when rollback notification is received

        'Declare done on the enlistment
        myEnlistment.Done()
    End Sub

    Public Sub InDoubt(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.InDoubt
        Console.WriteLine("In doubt notification received")

        'Do any work necessary when in doubt notification is received

        'Declare done on the enlistment
        myEnlistment.Done()
    End Sub
End Class

Optymalizacja wydajności

Transaction Klasa udostępnia także EnlistPromotableSinglePhase metodę, aby zarejestrować awansowanie jednego etapu rejestracji (PSPE). Dzięki temu trwałe zasobu manager (MB), hosta i "własnością" transakcji, która może zostać później przekazany do były zarządzane przez MSDTC, jeśli to konieczne. Aby uzyskać więcej informacji na ten temat, zobacz Optymalizacja przy użyciu zatwierdzania jednofazowego i promotable jednofazowego powiadomienia.

Zobacz też