https://msdn.microsoft.com/zh-cn/biztalk/ms751493

本示例演示如何使用消息队列 (MSMQ) 执行已经过事务处理的排队通信。

注意

本主题的末尾介绍了此示例的设置过程和生成说明。

在排队通信中,客户端使用队列与服务进行通信。 更确切地说,客户端向队列发送消息。 服务从队列接收消息。 因此,不必同时运行服务和客户端便可使用队列进行通信。

当事务用于发送和接收消息时,实际上有两个单独的事务。 当客户端在事务范围内发送消息时,事务相对于客户端和客户端队列管理器来说是本地事务。 当服务在事务范围内接收消息时,事务相对于服务和接收队列管理器来说是本地事务。 请务必牢记,客户端和服务不会参与同一个事务;实际上,它们在对队列执行操作(如发送和接收)时使用的是不同的事务。

在本示例中,客户端在事务范围内向服务发送一批消息。 然后,服务在服务定义的事务范围内接收发送到队列的消息。

服务协定为 IOrderProcessor,如下面的示例代码所示。 此接口定义了适合与队列一起使用的单向服务。

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

服务行为通过将 TransactionScopeRequired 设置为 true 来定义操作行为。 这可确保此方法所访问的任何资源管理器都使用相同的事务范围从队列中检索消息。 它还确保在方法引发异常的情况下,将消息返回到队列。 如果未设置操作行为,队列通道会创建一个从队列中读取消息的事务,并在调度前自动提交该事务,这样当操作失败时,消息将丢失。 对于服务操作而言,最常见的方案是在用于从队列中读取消息的事务中进行登记,如下面的代码中所示。


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

}

服务是自承载服务。 使用 MSMQ 传输时,必须提前创建所使用的队列。 可以手动或通过代码完成此操作。 在此示例中,该服务包含代码,以检查队列是否存在并在不存在时创建队列。 从配置文件中读取队列名称。 ServiceModel 元数据实用工具 (Svcutil.exe) 使用该基址来生成服务的代理。

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

MSMQ 队列名称在配置文件的 appSettings 节中指定,如以下示例配置所示。

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

队列名称为本地计算机使用圆点 (.),并在使用 System.Messaging 创建队列时在其路径中使用反斜杠分隔符。 Windows Communication Foundation (WCF) 终结点使用具有 net.msmq 方案的队列地址,使用“localhost”来表示本地计算机,并在其路径中使用正斜杠。

客户端创建事务范围。 与队列的通信发生在事务范围之内,从而可将该事务范围视为原子单元,其中所有消息均将发送到队列或者没有任何消息发送到队列。 通过在事务范围上调用 Complete 可以提交事务。

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

若要验证事务正在运行,请按照下面的示例代码注释事务范围来修改客户端,重新生成解决方案并运行客户端。

//scope.Complete();

因为事务没有完成,所以消息未发送到队列。

运行示例时,客户端和服务活动将显示在服务和客户端控制台窗口中。 您可以看到服务从客户端接收消息。 在每个控制台窗口中按 Enter 可以关闭服务和客户端。 请注意:由于正在使用队列,因此不必同时启动和运行客户端和服务。 可以先运行客户端,再将其关闭,然后启动服务,这样服务仍然会收到客户端的消息。

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

设置、生成和运行示例

  1. 如果先运行服务,则它将检查以确保队列存在。 如果队列不存在,则服务将创建一个队列。 可以先运行服务以创建队列或通过 MSMQ 队列管理器创建一个队列。 执行下面的步骤来在 Windows 2008 中创建队列。

    1. 在 Visual Studio 2012 中打开服务器管理器。

    2. 展开“功能”选项卡。

    3. 右击“私有消息队列”,然后选择“新建”“专用队列”

    4. 选中“事务性”框。

    5. 输入 ServiceModelSamplesTransacted 作为新队列的名称。

  2. 若要生成 C# 或 Visual Basic .NET 版本的解决方案,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。

  3. 若要用单机配置或跨计算机配置来运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。

默认情况下使用 NetMsmqBinding 启用传输安全。 对于 MSMQ 传输安全存在两个相关属性: 和 。 默认情况下,身份验证模式设置为 Windows,保护级别设置为 Sign。 为了使 MSMQ 提供身份验证和签名功能,MSMQ 必须是域的一部分,并且必须安装 MSMQ 的 Active Directory 集成选项。 如果在未满足这些条件的计算机上运行此示例,将会收到错误。

在加入到工作组或在没有 Active Directory 集成的计算机上运行示例

  1. 如果计算机不是域成员或尚未安装 Active Directory 集成,请将身份验证模式和保护级别设置为 None 以关闭传输安全性,如下面的示例配置代码所示。

    <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. 确保在运行示例前更改服务器和客户端上的配置。

    注意

    securitymode 设置为 None 等效于将 、 和 Message 安全设置为 None

已经过事务处理的 MSMQ 绑定(转载)的更多相关文章

  1. 基于MSMQ绑定的WCF服务实现总结

    一. 创建消息队列    1 1) 创建一个非事物性的私有队列    1 2)设置消息队列访问权限    2 二.创建WCF服务并绑定消息队列    4 1)创建HelloService服务    4 ...

  2. 实战WCF中net.tcp和net.msmq绑定协议

    平时很少写博文的,以前都是转载其他园友的文章,这几天有时间就自己尝试写一些wcf相关的文章,希望能给有需要的人带来一点帮助吧,水平有限再加上初次动手,写得不好还请多多包含!废话不多说了直接进入正题. ...

  3. ASP.NET Core MVC 模型绑定 (转载)

    ASP.NET Core MVC的Model Binding会将HTTP Request数据,以映射的方式对应到参数中.基本上跟ASP.NET MVC差不多,但能Binding的来源更多了一些.本篇将 ...

  4. .NET分布式事务处理总结【下】 - 包含MSMQ的分布式事务处理

    转自:http://www.cnblogs.com/daxnet/archive/2011/03/15/1984995.html .NET直接提供对MSMQ的访问支持,只需要添加System.Mess ...

  5. 浩哥解析MyBatis源码(十二)——binding绑定模块之MapperRegisty

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6758456.html 1.回顾 之前解析了解析模块parsing,其实所谓的解析模块就是为 ...

  6. MyBatis源码解析(十二)——binding绑定模块之MapperRegisty

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6758456.html 1.回顾 之前解析了解析模块parsing,其实所谓的解析模块就是为 ...

  7. WCF(五) 深入理解绑定

    适用于本机WCF-WCF交互性能最佳的绑定: 允许跨主机,但只能用于部署同一台主机上,不能访问命名管道 netNamePipeBinding总结 一 WCF与SOA SOA是一种通过为所有软件提供服务 ...

  8. Centos7网卡绑定的方法

    温和的方式请参考:https://www.cnblogs.com/zzf0305/p/9594093.html 一:传统的bond方式(饭已验证)------------本种的绑定方式比较暴躁 (1) ...

  9. WCF 服务编程 - 常用绑定

    WCF  定义了5中常用的绑定. 一. 绑定 1.基本绑定: 对应于BasicHttpBinding类.基本绑定能够将WCF服务公开为传统的ASMX Web服务,使得原客户端能够与新的服务协作.如果客 ...

随机推荐

  1. UML大战需求分析——阅读笔记03

    读<UML大战需求分析>有感03 状态机图和活动图在样子比较相似,但状态机图是用来为对象的状态及造成状态改变的事件建模.我们大二学习UML统一建模语言状态机图模块时了解到,UML的状态机图 ...

  2. DevExpress.XtraEditors.xtraScrollableControl

    DevExpress.XtraEditors.xtraScrollableControl里面加一个有高度的控件就有滚动条了

  3. 亚马逊S3下载上传文件

    引用网址: http://www.jxtobo.com/27697.html 下载 CloudBerry Explorer http://www.cloudberrylab.com/download- ...

  4. Go语言 Cookie的使用

    首先看看Cookie的结构体 type Cookie struct { Name string Value string Path string // optional Domain string / ...

  5. sql语句,怎么取查询结果的位置

    SQL 中的 substring 函数是用来抓出一个栏位资料中的其中一部分.这个函数的名称在不同的资料库中不完全一样: MySQL: SUBSTR( ), SUBSTRING( ) Oracle: S ...

  6. Python 判断变量的类型

    这里有两种方法.type 和isinstance import types aaa = 0 print type(aaa) if type(aaa) is types.IntType: print & ...

  7. delphi 步长不等于 1 的方法

    i:=; do begin ... INC(i,); end; 不能用for循环,只能用像上面的方法折衷一下

  8. QuanbenSoft Windows Runtime (Windows Store)Apps 应用及其框架总览

    Parrot Simple audio repeater for language learners http://www.windowsphone.com/en-au/store/app/parro ...

  9. mysql数据库表的自增主键号不规律,重新排列

    mysql数据库表的自增主键ID乱了,需要重新排序. 原理:删除原有的自增ID,重新建立新的自增ID. 1.删除原有主键: ALTER TABLE `table_name` DROP `id`; 2. ...

  10. java DOM4J 读取XML

    最近学习Java,在处理XML文档的时候,查阅相关资料,发现了DOM4J这个jre库,相对C#的XML处理来说,功能还算是跟得上 下面展示一篇我自己写的一个XML读取测试 import java.ut ...