Abgewickelte MSMQ-BindungTransacted MSMQ Binding

In diesem Beispiel wird veranschaulicht, wie eine abgewickelte Warteschlangenkommunikation mithilfe von Message Queuing (MSMQ) durchgeführt wird.This sample demonstrates how to perform transacted queued communication by using Message Queuing (MSMQ).

Hinweis

Die Setupprozedur und die Buildanweisungen für dieses Beispiel befinden sich am Ende dieses Themas.The setup procedure and build instructions for this sample are located at the end of this topic.

In einer Warteschlangenkommunikation kommuniziert der Client über eine Warteschlange mit dem Dienst.In queued communication, the client communicates to the service using a queue. Genauer ausgedrückt bedeutet dies, dass der Client Nachrichten an eine Warteschlange sendet.More precisely, the client sends messages to a queue. Der Dienst empfängt Nachrichten aus der Warteschlange.The service receives messages from the queue. Folglich müssen der Dienst und der Client nicht gleichzeitig ausgeführt werden, um über eine Warteschlange zu kommunizieren.The service and client, therefore, do not have to be running at the same time to communicate using a queue.

Wenn Transaktionen verwendet werden, um Nachrichten zu senden und zu empfangen, gibt es genau genommen zwei separate Transaktionen.When transactions are used to send and receive messages, there are actually two separate transactions. Wenn der Client innerhalb des Geltungsbereichs einer Transaktion Nachrichten sendet, gilt die Transaktion lokal für den Client und den Warteschlangen-Manager des Clients.When the client sends messages within the scope of a transaction, the transaction is local to the client and the client queue manager. Wenn der Dienst innerhalb des Geltungsbereichs der Transaktion Nachrichten empfängt, gilt die Transaktion lokal für den Dienst und den empfangenden Warteschlangen-Manager.When the service receives messages within the scope of the transaction, the transaction is local to the service and the receiving queue manager. Es ist wichtig, daran zu denken, dass der Client und der Dienst nicht an derselben Transaktion beteiligt sind, sondern zur Durchführung ihrer Vorgänge (wie Senden und Empfangen) über die Warteschlange verschiedene Transaktionen verwenden.It is very important to remember that the client and the service are not participating in the same transaction; rather, they are using different transactions when performing their operations (such as send and receive) with the queue.

In diesem Beispiel sendet der Client einen Nachrichtenbatch aus dem Geltungsbereich einer Transaktion an den Dienst.In this sample, the client sends a batch of messages to the service from within the scope of a transaction. Die an die Warteschlange gesendeten Nachrichten werden dann vom Dienst innerhalb des vom Dienst definierten Geltungsbereichs der Transaktion empfangen.The messages sent to the queue are then received by the service within the transaction scope defined by the service.

Der Dienstvertrag lautet IOrderProcessor, wie im folgenden Beispielcode gezeigt.The service contract is IOrderProcessor, as shown in the following sample code. Die Schnittstelle definiert einen unidirektionalen Dienst, der für die Verwendung mit Warteschlangen geeignet ist.The interface defines a one-way service that is suitable for use with queues.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]  
public interface IOrderProcessor  
{  
    [OperationContract(IsOneWay = true)]  
    void SubmitPurchaseOrder(PurchaseOrder po);  
}  

Das Dienstverhalten definiert ein Vorgangsverhalten, wobei TransactionScopeRequired auf true gesetzt ist.The service behavior defines an operation behavior with TransactionScopeRequired set to true. Auf diese Weise wird sichergestellt, dass alle Ressourcen-Manager, auf die diese Methode zugreift, denselben Geltungsbereich einer Transaktion verwenden, der auch zum Abrufen der Nachricht aus der Warteschlange verwendet wurde.This ensures that the same transaction scope that is used to retrieve the message from the queue is used by any resource managers accessed by the method. Des Weiteren wird gewährleistet, dass die Nachricht an die Warteschlange zurückgegeben wird, wenn die Methode eine Ausnahme auslöst.It also guarantees that if the method throws an exception, the message is returned to the queue. Ohne Festlegung dieses Vorgangsverhaltens erstellt ein in der Warteschlange stehender Kanal eine Transaktion, um die Nachricht aus der Warteschlange zu lesen, und führt dafür automatisch vor der Verteilung einen Commit aus, sodass die Nachricht verloren geht, falls der Vorgang fehlschlägt.Without setting this operation behavior, a queued channel creates a transaction to read the message from the queue and commits it automatically before dispatch such that if the operation fails, the message is lost. Das häufigste Szenario betrifft Dienstvorgänge, die sich in der Transaktion zum Lesen der Nachricht aus der Warteschlange eintragen, wie im folgenden Code veranschaulicht.The most common scenario is for service operations to enlist in the transaction that is used to read the message from the queue, as demonstrated in the following code.

 // This service class that implements the service contract.  
 // This added code writes output to the console window.  
 public class OrderProcessorService : IOrderProcessor  
 {  
     [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]  
     public void SubmitPurchaseOrder(PurchaseOrder po)  
     {  
         Orders.Add(po);  
         Console.WriteLine("Processing {0} ", po);  
     }  
  …  
}  

Der Dienst ist selbst gehostet.The service is self hosted. Bei Verwendung des MSMQ-Transports muss die Warteschlange im Voraus erstellt werden.When using the MSMQ transport, the queue used must be created in advance. Dies kann manuell erfolgen oder mithilfe eines Codes.This can be done manually or through code. In diesem Beispiel enthält der Dienst einen Code, um zu überprüfen, ob die Warteschlange bereits vorhanden ist, und um die Warteschlange gegebenenfalls zu erstellen.In this sample, the service contains code to check for the existence of the queue and create the queue if it does not exist. Der Warteschlangenname wird aus der Konfigurationsdatei gelesen.The queue name is read from the configuration file. Die Basisadresse wird verwendet, durch die ServiceModel Metadata Utility Tool (Svcutil.exe) auf den Proxy an den Dienst zu generieren.The base address is used by the ServiceModel Metadata Utility Tool (Svcutil.exe) to generate the proxy to the service.

// Host the service within this EXE console application.  
public static void Main()  
{  
    // Get the MSMQ queue name from appSettings in configuration.  
    string queueName = ConfigurationManager.AppSettings["queueName"];  

    // Create the transacted MSMQ queue if necessary.  
    if (!MessageQueue.Exists(queueName))  
        MessageQueue.Create(queueName, true);  

    // Create a ServiceHost for the OrderProcessorService type.  
    using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))  
    {  
        // Open the ServiceHost to create listeners and start listening for messages.  
        serviceHost.Open();  

        // The service can now be accessed.  
        Console.WriteLine("The service is ready.");  
        Console.WriteLine("Press <ENTER> to terminate service.");  
        Console.WriteLine();  
        Console.ReadLine();  

        // Close the ServiceHost to shut down the service.  
        serviceHost.Close();  
    }  
}  

Der Name der MSMQ-Warteschlange wird im appSettings-Abschnitt der Konfigurationsdatei angegeben, wie in der folgenden Beispielkonfiguration gezeigt.The MSMQ queue name is specified in an appSettings section of the configuration file, as shown in the following sample configuration.

<appSettings>  
    <add key="queueName" value=".\private$\ServiceModelSamplesTransacted" />  
</appSettings>  

Hinweis

Im Warteschlangennamen werden ein Punkt (.) für den lokalen Computer und umgekehrte Schrägstriche als Trennzeichen in der Pfadangabe verwendet, wenn die Warteschlange mithilfe von System.Messaging erstellt wird.The queue name uses a dot (.) for the local computer and backslash separators in its path when creating the queue using System.Messaging. Der Windows Communication Foundation (WCF)Windows Communication Foundation (WCF)-Endpunkt verwendet die Warteschlangenadresse mit dem net.msmq-Schema, localhost zur Angabe des lokalen Computers und Schrägstriche in der Pfadangabe.The Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) endpoint uses the queue address with net.msmq scheme, uses "localhost" to denote the local computer, and uses forward slashes in its path.

Der Client erstellt einen Geltungsbereich für die Transaktion.The client creates a transaction scope. Die Kommunikation mit der Warteschlange findet innerhalb des Geltungsbereichs der Transaktion statt, sodass diese in der Folge als unteilbare Einheit behandelt wird, in der entweder alle oder keine Nachrichten an die Warteschlange gesendet werden.Communication with the queue takes place within the scope of the transaction, causing it to be treated as an atomic unit where all messages are sent to the queue or none of the messages are sent to the queue. Für die Transaktion wird ein Commit ausgeführt, indem Complete im Geltungsbereich der Transaktion aufgerufen wird.The transaction is committed by calling Complete on the transaction scope.

// Create a client.  
OrderProcessorClient client = new OrderProcessorClient();  

// Create the purchase order.  
PurchaseOrder po = new PurchaseOrder();  
po.CustomerId = "somecustomer.com";  
po.PONumber = Guid.NewGuid().ToString();  

PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();  
lineItem1.ProductId = "Blue Widget";  
lineItem1.Quantity = 54;  
lineItem1.UnitCost = 29.99F;  

PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();  
lineItem2.ProductId = "Red Widget";  
lineItem2.Quantity = 890;  
lineItem2.UnitCost = 45.89F;  

po.orderLineItems = new PurchaseOrderLineItem[2];  
po.orderLineItems[0] = lineItem1;  
po.orderLineItems[1] = lineItem2;  

// Create a transaction scope.  
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))  
{  
    // Make a queued call to submit the purchase order.  
    client.SubmitPurchaseOrder(po);  
    // Complete the transaction.  
    scope.Complete();  
}  

// Closing the client gracefully closes the connection and cleans up resources.  
client.Close();  

Console.WriteLine();  
Console.WriteLine("Press <ENTER> to terminate client.");  
Console.ReadLine();  

Um zu überprüfen, dass Transaktionen funktionieren, ändern Sie den Client, indem Sie den Geltungsbereich einer Transaktion, wie im folgenden Beispielcode gezeigt, kommentieren, die Projektmappe neu erstellen und den Client ausführen.To verify that transactions are working, modify the client by commenting the transaction scope as shown in the following sample code, rebuild the solution, and run the client.

//scope.Complete();  

Da die Transaktion nicht abgeschlossen wird, werden die Nachrichten nicht an die Warteschlange gesendet.Because the transaction is not completed, the messages are not sent to the queue.

Wenn Sie das Beispiel ausführen, werden die Client- und Dienstaktivitäten sowohl im Dienst- als auch im Clientkonsolenfenster angezeigt.When you run the sample, the client and service activities are displayed in both the service and client console windows. Sie können sehen, wie der Dienst Nachrichten vom Client empfängt.You can see the service receive messages from the client. Drücken Sie die EINGABETASTE in den einzelnen Konsolenfenstern, um den Dienst und den Client zu schließen.Press ENTER in each console window to shut down the service and client. Beachten Sie, dass aufgrund der Verwendung einer Warteschlange der Client und der Dienst nicht gleichzeitig ausgeführt werden müssen.Note that because queuing is in use, the client and service do not have to be up and running at the same time. Sie können den Client ausführen, ihn schließen und anschließend den Dienst starten, der dann trotzdem noch die Nachrichten des Clients empfängt.You can run the client, shut it down, and then start up the service and it still receives the messages.

The service is ready.  
Press <ENTER> to terminate service.  

Processing Purchase Order: 7b31ce51-ae7c-4def-9b8b-617e4288eafd  
        Customer: somecustomer.com  
        OrderDetails  
                Order LineItem: 54 of Blue Widget @unit price: $29.99  
                Order LineItem: 890 of Red Widget @unit price: $45.89  
        Total cost of this order: $42461.56  
        Order status: Pending  

So können Sie das Beispiel einrichten, erstellen und ausführenTo set up, build, and run the sample

  1. Stellen Sie sicher, dass Sie ausgeführt haben die Setupprozedur für die Windows Communication Foundation-Beispiele zum einmaligen.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Wenn der Dienst zuerst ausgeführt wird, wird überprüft, ob die Warteschlange vorhanden ist.If the service is run first, it will check to ensure that the queue is present. Ist die Warteschlange nicht vorhanden, wird sie vom Dienst erstellt.If the queue is not present, the service will create one. Sie können zuerst den Dienst ausführen, um die Warteschlange zu erstellen, oder Sie können sie über den MSMQ-Warteschlangen-Manager erstellen.You can run the service first to create the queue, or you can create one via the MSMQ Queue Manager. Führen Sie zum Erstellen einer Warteschlange in Windows 2008 die folgenden Schritte aus:Follow these steps to create a queue in Windows 2008.

    1. Öffnen Sie Server-Manager in Visual Studio 2012Visual Studio 2012.Open Server Manager in Visual Studio 2012Visual Studio 2012.

    2. Erweitern Sie die Funktionen Registerkarte.Expand the Features tab.

    3. Mit der rechten Maustaste Private Meldungswarteschlangen, und wählen Sie neu, Private Warteschlange.Right-click Private Message Queues, and select New, Private Queue.

    4. Überprüfen Sie die transaktional Feld.Check the Transactional box.

    5. Geben Sie ServiceModelSamplesTransacted als Namen für die neue Warteschlange.Enter ServiceModelSamplesTransacted as the name of the new queue.

  3. Um die C#- oder Visual Basic .NET-Edition der Projektmappe zu erstellen, befolgen Sie die unter Building the Windows Communication Foundation Samplesaufgeführten Anweisungen.To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  4. Um das Beispiel in einer Einzelcomputer- oder computerübergreifenden Konfiguration ausführen möchten, folgen Sie den Anweisungen Ausführen der Windows Communication Foundation-Beispiele.To run the sample in a single- or cross-computer configuration, follow the instructions in Running the Windows Communication Foundation Samples.

Standardmäßig wird mit NetMsmqBinding die Transportsicherheit aktiviert.By default with the NetMsmqBinding, transport security is enabled. Es gibt zwei relevante Eigenschaften für die MSMQ-Transportsicherheit, MsmqAuthenticationMode und MsmqProtectionLevel.There are two relevant properties for MSMQ transport security, MsmqAuthenticationMode and MsmqProtectionLevel. Standardmäßig wird der Authentifizierungsmodus als Windows festgelegt, und die Schutzebene wird auf Sign gesetzt.By default, the authentication mode is set to Windows and the protection level is set to Sign. Damit MSMQ die Authentifizierungs- und Signierungs-Funktion zur Verfügung stellt, muss es Teil einer Domäne sein, und die Option zur Active Directory-Integration muss für MSMQ installiert sein.For MSMQ to provide the authentication and signing feature, it must be part of a domain and the Active Directory integration option for MSMQ must be installed. Wenn Sie dieses Beispiel auf einem Computer ausführen, der diese Kriterien nicht erfüllt, erhalten Sie eine Fehlermeldung.If you run this sample on a computer that does not satisfy these criteria, you receive an error.

So führen Sie das Beispiel auf einem Computer aus, der sich in einer Arbeitsgruppe befindet oder über keine Active Directory-Integration verfügtTo run the sample on a computer joined to a workgroup or without Active Directory integration

  1. Wenn Ihr Computer nicht zu einer Domäne gehört oder auf ihm keine Active Directory-Integration installiert ist, deaktivieren Sie die Transportsicherheit, indem Sie den Authentifizierungsmodus und die Schutzebene auf None setzen, wie im folgenden Beispiel für einen Konfigurationscode gezeigt.If your computer is not part of a domain or does not have Active Directory integration installed, turn off transport security by setting the authentication mode and protection level to None as shown in the following sample configuration code.

    <system.serviceModel>  
      <services>  
        <service name="Microsoft.ServiceModel.Samples.OrderProcessorService"  
                 behaviorConfiguration="OrderProcessorServiceBehavior">  
          <host>  
            <baseAddresses>  
              <add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>  
            </baseAddresses>  
          </host>  
          <!-- Define NetMsmqEndpoint. -->  
          <endpoint  
              address="net.msmq://localhost/private/ServiceModelSamplesTransacted"  
              binding="netMsmqBinding"  
              bindingConfiguration="Binding1"  
           contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />  
          <!-- The mex endpoint is explosed at http://localhost:8000/ServiceModelSamples/service/mex. -->  
          <endpoint address="mex"  
                    binding="mexHttpBinding"  
                    contract="IMetadataExchange" />  
        </service>  
      </services>  
    
      <bindings>  
        <netMsmqBinding>  
          <binding name="Binding1">  
            <security mode="None" />  
          </binding>  
        </netMsmqBinding>  
      </bindings>  
    
        <behaviors>  
          <serviceBehaviors>  
            <behavior name="OrderProcessorServiceBehavior">  
              <serviceMetadata httpGetEnabled="True"/>  
            </behavior>  
          </serviceBehaviors>  
        </behaviors>  
    
      </system.serviceModel>  
    
  2. Ändern Sie die Konfiguration sowohl auf dem Server als auch auf dem Client, bevor Sie das Beispiel ausführen.Ensure that you change the configuration on both the server and the client before you run the sample.

    Hinweis

    Das Festlegen von security``mode auf None entspricht dem Festlegen von MsmqAuthenticationMode, MsmqProtectionLevel und der Message-Sicherheit auf None.Setting security``mode to None is equivalent to setting MsmqAuthenticationMode, MsmqProtectionLevel, and Message security to None.

Wichtig

Die Beispiele sind möglicherweise bereits auf dem Computer installiert.The samples may already be installed on your computer. Suchen Sie nach dem folgenden Verzeichnis (Standardverzeichnis), bevor Sie fortfahren.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Wenn dieses Verzeichnis nicht vorhanden ist, rufen Sie Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 auf, um alle Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) - und WFWF -Beispiele herunterzuladen.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) and WFWF samples. Dieses Beispiel befindet sich im folgenden Verzeichnis.This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Basic\Binding\Net\MSMQ\Transacted

Siehe auchSee Also