Udostępnij za pośrednictwem


Przepływ transakcji WS

Przykład TransactionFlow demonstruje użycie transakcji koordynowanej przez klienta oraz opcji klienta i serwera dla przepływu transakcji przy użyciu protokołu WS-Atomic Transaction lub OleTransactions. Ten przykład jest oparty na artykule Wprowadzenie , które implementuje usługę kalkulatora, ale operacje są przypisywane w celu zademonstrowania użycia TransactionFlowAttribute elementu z wyliczaniem TransactionFlowOption w celu określenia stopnia włączenia przepływu transakcji. W zakresie przepływanej transakcji dziennik żądanych operacji jest zapisywany w bazie danych i utrzymuje się do momentu zakończenia skoordynowanej transakcji klienta — jeśli transakcja klienta nie zostanie ukończona, transakcja usługi sieci Web gwarantuje, że odpowiednie aktualizacje bazy danych nie zostaną zatwierdzone.

Uwaga

Procedura instalacji i instrukcje kompilacji dla tego przykładu znajdują się na końcu tego tematu.

Po zainicjowaniu połączenia z usługą i transakcją klient uzyskuje dostęp do kilku operacji usługi. Kontrakt dla usługi jest definiowany w następujący sposób, a każda z operacji demonstruje inne ustawienie dla elementu TransactionFlowOption.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    double Add(double n1, double n2);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Allowed)]
    double Subtract(double n1, double n2);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.NotAllowed)]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2);
}

Definiuje to operacje w kolejności ich przetwarzania:

  • Żądanie Add operacji musi zawierać transakcję przepływową.

  • Subtract Żądanie operacji może zawierać transakcję przepływową.

  • Multiply Żądanie operacji nie może zawierać transakcji przepływanej za pośrednictwem jawnego ustawienia NotAllowed.

  • Divide Żądanie operacji nie może zawierać transakcji przepływanej przez pominięcie atrybutuTransactionFlow.

Aby włączyć przepływ transakcji, powiązania z włączoną właściwością <transactionFlow> muszą być używane oprócz odpowiednich atrybutów operacji. W tym przykładzie konfiguracja usługi uwidacznia punkt końcowy TCP i punkt końcowy HTTP oprócz punktu końcowego wymiany metadanych. Punkt końcowy TCP i punkt końcowy HTTP używają następujących powiązań, z których obie mają włączoną <właściwość transactionFlow> .

<bindings>
  <netTcpBinding>
    <binding name="transactionalOleTransactionsTcpBinding"
             transactionFlow="true"
             transactionProtocol="OleTransactions"/>
  </netTcpBinding>
  <wsHttpBinding>
    <binding name="transactionalWsatHttpBinding"
             transactionFlow="true" />
  </wsHttpBinding>
</bindings>

Uwaga

Zapewniana przez system funkcja netTcpBinding umożliwia określenie wartości transactionProtocol, natomiast wsHttpBinding dostarczany przez system używa tylko bardziej współdziałającego protokołu WSAtomicTransactionOctober2004. Protokół OleTransactions jest dostępny tylko do użytku przez klientów programu Windows Communication Foundation (WCF).

Dla klasy, która implementuje ICalculator interfejs, wszystkie metody są przypisywane z właściwością ustawioną TransactionScopeRequired na true. To ustawienie deklaruje, że wszystkie akcje wykonywane w ramach metody występują w zakresie transakcji. W takim przypadku akcje podjęte obejmują rejestrowanie w bazie danych dzienników. Jeśli żądanie operacji zawiera przepływaną transakcję, akcje są wykonywane w zakresie transakcji przychodzącej lub zostanie automatycznie wygenerowany nowy zakres transakcji.

Uwaga

Właściwość TransactionScopeRequired definiuje zachowanie lokalne implementacji metod usługi i nie definiuje możliwości lub wymagania klienta dotyczące przepływu transakcji.

// Service class that implements the service contract.
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable)]
public class CalculatorService : ICalculator
{
    [OperationBehavior(TransactionScopeRequired = true)]
    public double Add(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Adding {0} to {1}", n1, n2));
        return n1 + n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Subtract(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Subtracting {0} from {1}", n2, n1));
        return n1 - n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Multiply(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Multiplying {0} by {1}", n1, n2));
        return n1 * n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Divide(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Dividing {0} by {1}", n1, n2));
        return n1 / n2;
    }

    // Logging method omitted for brevity
}

Na kliencie ustawienia usługi TransactionFlowOption w operacjach są odzwierciedlane w wygenerowanej definicji interfejsu ICalculator klienta. Ponadto ustawienia właściwości usługi transactionFlow są odzwierciedlane w konfiguracji aplikacji klienta. Klient może wybrać transport i protokół, wybierając odpowiedni endpointConfigurationNameelement .

// Create a client using either wsat or oletx endpoint configurations
CalculatorClient client = new CalculatorClient("WSAtomicTransaction_endpoint");
// CalculatorClient client = new CalculatorClient("OleTransactions_endpoint");

Uwaga

Obserwowane zachowanie tego przykładu jest takie samo niezależnie od wybranego protokołu lub transportu.

Po zainicjowaniu połączenia z usługą klient tworzy nowe TransactionScope wywołania operacji usługi.

// Start a transaction scope
using (TransactionScope tx =
            new TransactionScope(TransactionScopeOption.RequiresNew))
{
    Console.WriteLine("Starting transaction");

    // Call the Add service operation
    //  - generatedClient will flow the required active transaction
    double value1 = 100.00D;
    double value2 = 15.99D;
    double result = client.Add(value1, value2);
    Console.WriteLine("  Add({0},{1}) = {2}", value1, value2, result);

    // Call the Subtract service operation
    //  - generatedClient will flow the allowed active transaction
    value1 = 145.00D;
    value2 = 76.54D;
    result = client.Subtract(value1, value2);
    Console.WriteLine("  Subtract({0},{1}) = {2}", value1, value2, result);

    // Start a transaction scope that suppresses the current transaction
    using (TransactionScope txSuppress =
                new TransactionScope(TransactionScopeOption.Suppress))
    {
        // Call the Subtract service operation
        //  - the active transaction is suppressed from the generatedClient
        //    and no transaction will flow
        value1 = 21.05D;
        value2 = 42.16D;
        result = client.Subtract(value1, value2);
        Console.WriteLine("  Subtract({0},{1}) = {2}", value1, value2, result);

        // Complete the suppressed scope
        txSuppress.Complete();
    }

    // Call the Multiply service operation
    // - generatedClient will not flow the active transaction
    value1 = 9.00D;
    value2 = 81.25D;
    result = client.Multiply(value1, value2);
    Console.WriteLine("  Multiply({0},{1}) = {2}", value1, value2, result);

    // Call the Divide service operation.
    // - generatedClient will not flow the active transaction
    value1 = 22.00D;
    value2 = 7.00D;
    result = client.Divide(value1, value2);
    Console.WriteLine("  Divide({0},{1}) = {2}", value1, value2, result);

    // Complete the transaction scope
    Console.WriteLine("  Completing transaction");
    tx.Complete();
}

Console.WriteLine("Transaction committed");

Wywołania operacji są następujące:

  • Żądanie Add przepływa wymaganą transakcję do usługi, a akcje usługi są wykonywane w zakresie transakcji klienta.

  • Pierwsze Subtract żądanie przepływa również dozwoloną transakcję do usługi, a następnie ponownie akcje usługi są wykonywane w zakresie transakcji klienta.

  • Drugie Subtract żądanie jest wykonywane w ramach nowego zakresu transakcji zadeklarowanego TransactionScopeOption.Suppress za pomocą opcji . Spowoduje to pominięcie początkowej transakcji zewnętrznej klienta, a żądanie nie przepływa transakcji do usługi. Takie podejście pozwala klientowi jawnie zrezygnować i chronić przed przepływem transakcji do usługi, jeśli nie jest to wymagane. Akcje usługi są wykonywane w zakresie nowej i niezałączonej transakcji.

  • Żądanie Multiply nie przepływa transakcji do usługi, ponieważ wygenerowana definicja interfejsu ICalculator klienta zawiera TransactionFlowAttribute zestaw .TransactionFlowOptionNotAllowed

  • Żądanie Divide nie przepływa transakcji do usługi, ponieważ ponownie wygenerowana definicja interfejsu ICalculator klienta nie zawiera TransactionFlowAttributeelementu . Akcje usługi są ponownie wykonywane w zakresie innej nowej i niepołączonej transakcji.

Po uruchomieniu przykładu żądania operacji i odpowiedzi są wyświetlane w oknie konsoli klienta. Naciśnij klawisz ENTER w oknie klienta, aby zamknąć klienta.

Starting transaction
  Add(100,15.99) = 115.99
  Subtract(145,76.54) = 68.46
  Subtract(21.05,42.16) = -21.11
  Multiply(9,81.25) = 731.25
  Divide(22,7) = 3.14285714285714
  Completing transaction
Transaction committed
Press <ENTER> to terminate client.

Rejestrowanie żądań operacji usługi jest wyświetlane w oknie konsoli usługi. Naciśnij klawisz ENTER w oknie klienta, aby zamknąć klienta.

Press <ENTER> to terminate the service.
  Writing row to database: Adding 100 to 15.99
  Writing row to database: Subtracting 76.54 from 145
  Writing row to database: Subtracting 42.16 from 21.05
  Writing row to database: Multiplying 9 by 81.25
  Writing row to database: Dividing 22 by 7

Po pomyślnym wykonaniu zakres transakcji klienta zostanie ukończony i wszystkie akcje podjęte w tym zakresie zostaną zatwierdzone. W szczególności zanotowane 5 rekordów jest utrwalanych w bazie danych usługi. Pierwsze 2 z nich wystąpiły w zakresie transakcji klienta.

Jeśli wystąpił wyjątek w dowolnym miejscu w obrębie klienta TransactionScope , transakcja nie może zakończyć się. Powoduje to, że rekordy zarejestrowane w tym zakresie nie zostaną zatwierdzone w bazie danych. Ten efekt można zaobserwować, powtarzając przykładowy przebieg po oznaczeniu komentarza wywołania w celu ukończenia zewnętrznego TransactionScope. W takim przebiegu rejestrowane są tylko ostatnie 3 akcje (z drugiego Subtract, Multiply i Divide żądania), ponieważ transakcja klienta nie przepływa do nich.

Aby skonfigurować, skompilować i uruchomić przykład

  1. Aby skompilować wersję rozwiązania w języku C# lub Visual Basic dla platformy .NET, postępuj zgodnie z instrukcjami w temacie Kompilowanie przykładów programu Windows Communication Foundation

  2. Upewnij się, że zainstalowano program SQL Server Express Edition lub SQL Server i że parametry połączenia został poprawnie ustawiony w pliku konfiguracji aplikacji usługi. Aby uruchomić przykład bez użycia bazy danych, ustaw usingSql wartość w pliku konfiguracji aplikacji usługi na wartość false

  3. Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w temacie Uruchamianie przykładów programu Windows Communication Foundation.

    Uwaga

    W przypadku konfiguracji między maszynami włącz koordynatora transakcji rozproszonych, korzystając z poniższych instrukcji, i użyj narzędzia WsatConfig.exe z zestawu Windows SDK, aby włączyć obsługę sieci transakcji WCF. Aby uzyskać informacje na temat konfigurowania WsatConfig.exe, zobacz Konfigurowanie obsługi transakcji niepodzielnych WS.

Niezależnie od tego, czy przykład jest uruchamiany na tym samym komputerze, czy na różnych komputerach, należy skonfigurować koordynatora transakcji rozproszonych firmy Microsoft (MSDTC), aby włączyć przepływ transakcji sieciowych i użyć narzędzia WsatConfig.exe w celu włączenia obsługi sieci transakcji WCF.

Aby skonfigurować koordynator transakcji rozproszonych firmy Microsoft (MSDTC) do obsługi uruchamiania przykładu

  1. Na maszynie usługi z systemem Windows Server 2003 lub Windows XP skonfiguruj MSDTC, aby zezwolić na przychodzące transakcje sieciowe, postępując zgodnie z tymi instrukcjami.

    1. W menu Start przejdź do Panel sterowania, a następnie Administracja istrative Tools, a następnie pozycję Component Services.

    2. Rozwiń węzeł Usługi składników. Otwórz folder Komputery.

    3. Kliknij prawym przyciskiem myszy pozycję Mój komputer i wybierz polecenie Właściwości.

    4. Na karcie MSDTC kliknij pozycję Konfiguracja zabezpieczeń.

    5. Sprawdź dostęp do sieci DTC i zezwalaj na ruch przychodzący.

    6. Kliknij przycisk OK, a następnie kliknij przycisk Tak , aby ponownie uruchomić usługę MSDTC.

    7. Kliknij przycisk OK, aby zamknąć okno dialogowe.

  2. Na maszynie usługi z systemem Windows Server 2008 lub Windows Vista skonfiguruj MSDTC, aby zezwolić na przychodzące transakcje sieciowe, postępując zgodnie z tymi instrukcjami.

    1. W menu Start przejdź do Panel sterowania, a następnie Administracja istrative Tools, a następnie pozycję Component Services.

    2. Rozwiń węzeł Usługi składników. Otwórz folder Komputery. Wybierz pozycję Koordynator transakcji rozproszonych.

    3. Kliknij prawym przyciskiem myszy pozycję Koordynator DTC i wybierz polecenie Właściwości.

    4. Na karcie Zabezpieczenia zaznacz pozycję Dostęp do sieci DTC i Zezwalaj na ruch przychodzący.

    5. Kliknij przycisk OK, a następnie kliknij przycisk Tak , aby ponownie uruchomić usługę MSDTC.

    6. Kliknij przycisk OK, aby zamknąć okno dialogowe.

  3. Na komputerze klienckim skonfiguruj msdTC, aby zezwalać na wychodzące transakcje sieciowe:

    1. Z menu Start przejdź do Control Panelpozycji , a następnie Administracja istrative Tools, a następnie do pozycji Usługi składowe.

    2. Kliknij prawym przyciskiem myszy pozycję Mój komputer i wybierz polecenie Właściwości.

    3. Na karcie MSDTC kliknij pozycję Konfiguracja zabezpieczeń.

    4. Sprawdź dostęp do sieci DTC i zezwalaj na ruch wychodzący.

    5. Kliknij przycisk OK, a następnie kliknij przycisk Tak , aby ponownie uruchomić usługę MSDTC.

    6. Kliknij przycisk OK, aby zamknąć okno dialogowe.