Pengikatan MSMQ yang Ditransaksikan

Contoh Transaksi menunjukkan cara melakukan komunikasi antrean transaksional dengan menggunakan Message Queuing (MSMQ).

Nota

Prosedur penyiapan dan instruksi build untuk sampel ini terletak di akhir topik ini.

Dalam komunikasi antrian, klien berkomunikasi dengan layanan menggunakan antrian. Lebih tepatnya, klien mengirim pesan ke daftar antrian. Layanan menerima pesan dari antrean. Oleh karena itu, layanan dan pelanggan tidak harus berjalan pada saat yang sama untuk berkomunikasi melalui antrean.

Ketika transaksi digunakan untuk mengirim dan menerima pesan, sebenarnya ada dua transaksi terpisah. Ketika klien mengirim pesan dalam cakupan transaksi, transaksi bersifat lokal untuk klien dan manajer antrean klien. Ketika layanan menerima pesan dalam cakupan transaksi, transaksi bersifat lokal untuk layanan dan manajer antrean penerima. Sangat penting untuk diingat bahwa klien dan layanan tidak berpartisipasi dalam transaksi yang sama; sebaliknya, mereka menggunakan transaksi yang berbeda saat melakukan operasi mereka (seperti mengirim dan menerima) dengan antrean.

Pada contoh ini, klien mengirim batch pesan ke layanan dari dalam cakupan transaksi. Pesan yang dikirim ke antrean kemudian diterima oleh layanan dalam cakupan transaksi yang ditentukan oleh layanan.

Kontrak layanan adalah IOrderProcessor, seperti yang ditunjukkan dalam kode sampel berikut. Antarmuka mendefinisikan layanan satu arah yang cocok untuk digunakan dengan antrian.

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

Perilaku layanan menentukan perilaku operasi dengan TransactionScopeRequired diatur ke true. Ini memastikan bahwa lingkup transaksi yang sama yang digunakan untuk mengambil pesan dari antrean digunakan oleh manajer sumber daya apa pun yang diakses oleh metode tersebut. Ini juga menjamin bahwa jika metode menghasilkan pengecualian, pesan dikembalikan ke dalam antrean. Tanpa mengatur perilaku operasi ini, saluran yang diantrekan membuat transaksi untuk membaca pesan dari antrean dan mengesahkannya secara otomatis sebelum diteruskan sehingga jika operasi gagal, pesan tersebut akan hilang. Skenario yang paling umum adalah operasi layanan untuk terlibat dalam transaksi yang digunakan untuk membaca pesan dari antrean, seperti yang ditunjukkan dalam kode berikut.

 // 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);
     }
  …
}

Layanan ini dihost sendiri. Saat menggunakan protokol transportasi MSMQ, antrean yang digunakan harus dibuat terlebih dahulu. Ini dapat dilakukan secara manual atau melalui kode. Dalam sampel ini, layanan berisi kode untuk memeriksa keberadaan antrean dan membuat antrean jika tidak ada. Nama antrean dibaca dari file konfigurasi. Alamat dasar digunakan oleh Alat Utilitas Metadata ServiceModel (Svcutil.exe) untuk menghasilkan proksi ke layanan.

// 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();
    }
}

Nama antrean MSMQ ditentukan di bagian appSettings dari file konfigurasi, seperti yang ditunjukkan dalam konfigurasi sampel berikut.

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

Nota

Nama antrean menggunakan titik (.) untuk komputer lokal dan garis miring terbalik dalam jalurnya saat membuat antrean menggunakan System.Messaging. Titik akhir Windows Communication Foundation (WCF) menggunakan alamat antrean dengan skema net.msmq, menggunakan "localhost" untuk menunjukkan komputer lokal, dan menggunakan garis miring ke depan pada jalurnya.

Klien membuat cakupan transaksi. Komunikasi dengan antrean terjadi dalam lingkup transaksi, menyebabkannya diperlakukan sebagai unit atom di mana semua pesan dikirim ke antrean atau tidak ada pesan yang dikirim ke antrean. Transaksi disahkan dengan memanggil Complete dalam cakupan transaksi.

// 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();

Untuk memverifikasi bahwa transaksi berfungsi, ubah klien dengan mengomentari cakupan transaksi seperti yang ditunjukkan dalam kode sampel berikut, membangun kembali solusi, dan menjalankan klien.

//scope.Complete();

Karena transaksi tidak selesai, pesan tidak dikirim ke antrean.

Saat Anda menjalankan sampel, aktivitas klien dan layanan ditampilkan di jendela layanan dan konsol klien. Anda dapat melihat layanan menerima pesan dari klien. Tekan ENTER di setiap jendela konsol untuk mematikan layanan dan klien. Perhatikan bahwa karena antrean digunakan, klien dan layanan tidak perlu berfungsi secara bersamaan. Anda dapat menjalankan klien, mematikannya, lalu memulai layanan dan masih menerima pesan.

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

Untuk menyiapkan, mengompilasi, dan menjalankan sampel

  1. Pastikan Anda telah melakukan Prosedur Penyiapan One-Time untuk Sampel Windows Communication Foundation.

  2. Jika layanan dijalankan terlebih dahulu, layanan akan memeriksa untuk memastikan bahwa antrean ada. Jika antrean belum ada, layanan akan membuatnya. Anda dapat menjalankan layanan terlebih dahulu untuk membuat antrean, atau Anda dapat membuatnya melalui MSMQ Queue Manager. Ikuti langkah-langkah ini untuk membuat antrean di Windows 2008.

    1. Buka Manajer Server di Visual Studio 2012.

    2. Perluas tab Fitur.

    3. Klik kanan Antrean Pesan Privat, dan pilih Baru, Antrean Privat.

    4. Centang kotak Transaksi.

    5. Masukkan ServiceModelSamplesTransacted sebagai nama antrean baru.

  3. Untuk membangun solusi edisi C# atau Visual Basic .NET, ikuti instruksi di Membangun Sampel Windows Communication Foundation.

  4. Untuk menjalankan sampel dalam konfigurasi satu atau lintas komputer, ikuti instruksi dalam Menjalankan Sampel Windows Communication Foundation.

Secara default dengan NetMsmqBinding, keamanan transportasi diaktifkan. Ada dua properti yang relevan untuk keamanan transportasi MSMQ, MsmqAuthenticationMode dan MsmqProtectionLevel. Secara default, mode autentikasi diatur ke Windows dan tingkat perlindungan diatur ke Sign. Agar MSMQ menyediakan fitur autentikasi dan penandatanganan, MSMQ harus menjadi bagian dari domain dan opsi integrasi Direktori Aktif untuk MSMQ harus diinstal. Jika Anda menjalankan sampel ini pada komputer yang tidak memenuhi kriteria ini, Anda menerima kesalahan.

Untuk menjalankan sampel di komputer yang bergabung ke grup kerja atau tanpa integrasi Direktori Aktif

  1. Jika komputer Anda bukan bagian dari domain atau tidak memiliki integrasi Direktori Aktif yang terinstal, nonaktifkan keamanan transportasi dengan mengatur mode autentikasi dan tingkat perlindungan ke None seperti yang ditunjukkan dalam kode konfigurasi sampel berikut.

    <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 exposed 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. Pastikan Anda mengubah konfigurasi di server dan klien sebelum menjalankan sampel.

    Nota

    Pengaturan security mode ke None setara dengan pengaturan MsmqAuthenticationMode, , MsmqProtectionLeveldan Message keamanan ke None.