我相信我已经找到了我的两个问题的答案......
对于Transactional
运营,我不相信存在“环境”交易。我已经通过在数据库操作后简单地抛出异常来证明这一点,果然,无论如何数据都已提交。我想知道是否有声明事务范围的首选方法,即:
[OperationBehavior(TransactionScopeRequired = true)]
public void MyServiceOperation(){ ... }
//or using the TransactionScope
public void MyServiceOperation()
{
using(var transScope = new TransactionScope(...)){ ... }
}
ReceiveContext
对于重试功能,您似乎需要启用以下博客:
[ServiceContract]
public interface IMyService
{
[OperationContract(IsOneWay=true)]
[ReceiveContextEnabled(ManualControl = true)]
void MyServiceOperation();
// and in the service implementation:
[OperationBehavior]
public void MyServiceOperation()
{
var incomingProperties = OperationContext.Current.IncomingMessageProperties;
var property = incomingProperties[BrokeredMessageProperty.Name] as BrokeredMessageProperty;
//Complete the Message
ReceiveContext receiveContext;
if (ReceiveContext.TryGet(incomingProperties, out receiveContext))
{
//Do Something
receiveContext.Complete(TimeSpan.FromSeconds(10.0d));
}
else
{
throw new InvalidOperationException("...");
}
}
更新:
在深入挖掘之后,我发现如果您使用普通的、合同优先、IIS 托管、带有 Service Bus 1.0 的 WCF,那么 OperationContext 完成并不是一个真正的选择(不知道为什么,但我我希望有人能对此有所了解)
我发现关于事务行为的唯一理智选项如下:
[OperationBehavior]
public void MyServiceOperation()
{
using(var transScope = new TransactionScope(...))
{
DbWork();
transScope.Complete();
}
Client.SendToServiceBus(); // <-- Cannot be part of transaction, otherwise
// exceptions will be thrown!
}
问题仍然是,这种模式与 MSMQ 不同,如果将消息发送到服务总线失败,则不允许回滚整个操作。(当然,除非有人知道得更好……)
这也意味着您被迫滚动自己的重试逻辑,并且可能有一些机制在下一步验证上一步是否已提交。呸!
据我了解,工作流服务和直接处理代理消息为您提供了一些开箱即用的重试功能。但是,如果您通过 AppFabric 使用 IIS 托管您的工作流服务,那么微软不知何故想出了如何让事务覆盖发送到服务总线。(如果有人知道那个机制是什么,请告诉我!)