长话短说?
解释问题的截屏视频:https://youtu.be/B-Q3T5KpiYk
问题
当从客户端流向服务的事务时,Transaction.Current 在等待 服务到服务调用后变为null。
当然,除非您在服务方法中创建一个新的 TransactionScope,如下所示:
[OperationBehavior(TransactionScopeRequired = true)]
public async Task CallAsync()
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
await _service.WriteAsync();
await _service.WriteAsync();
scope.Complete();
}
}
我不知道为什么默认情况下不启用 TransactionScopeAsyncFlowOption,但我不想重复自己所以我想我总是使用自定义行为创建一个带有该选项的内部事务范围。
问题更新
它甚至不必是服务到服务调用,对本地异步方法的等待也会使 Transaction.Current 为空。举例说明
[OperationBehavior(TransactionScopeRequired = true)]
public async Task CallAsync()
{
await WriteAsync();
// Transaction.Current is now null
await WriteAsync();
}
尝试的解决方案
我创建了一个 Message Inspector,实现了 IDispatchMessageInspector 并将其附加为服务行为,代码执行并且那里的一切都没有问题,但它与在服务方法中声明 transactionscope 的效果不同。
public class TransactionScopeMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
var transactionMessage = (TransactionMessageProperty)OperationContext.Current.IncomingMessageProperties["TransactionMessageProperty"];
var scope = new TransactionScope(transactionMessage.Transaction, TransactionScopeAsyncFlowOption.Enabled);
return scope;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
var transaction = correlationState as TransactionScope;
if (transaction != null)
{
transaction.Complete();
transaction.Dispose();
}
}
}
通过在调试时查看标识符,我可以看到消息检查器中的事务实际上与服务中的事务相同但是 在第一次通话之后,即
await _service_WriteAsync();
Transaction.Current 变为 null。如果没有从消息检查器中的 OperationContext.Current 获取当前事务也是一样,所以这不太可能是问题所在。
问题
有没有可能做到这一点?似乎唯一的方法是在服务方法中声明一个 TransactionScope,即:
public async Task CallAsync()
{
var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
await _service.WriteAsync();
await _service.WriteAsync();
scope.Complete();
}
对于以下服务契约,如果 transaction.current 在此期间变为 null,我们会在第二次服务调用时明显得到异常
[OperationContract, TransactionFlow(TransactionFlowOption.Mandatory)]
Task WriteAsync();
最佳答案
事实证明,我们真的不应该在服务器上将 async/await 关键字与分布式事务一起使用,请参阅 this blog post了解详情。
关于c# - 是否可以在自定义 WCF 服务行为中创建 TransactionScope? (异步、等待、TransactionScopeAsyncFlowOption.Enabled),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34767978/