Ajd*_*eek 8 c# wcf asynchronous transactionscope async-await
截屏解释问题: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();
}
}
Run Code Online (Sandbox Code Playgroud)
为什么默认情况下不启用TransactionScopeAsyncFlowOption我不知道,但我不想重复自己,所以我想我总是使用自定义行为创建一个带有该选项的内部事务管理器.
它甚至不必是服务调用服务,等待本地异步方法也使Transaction.Current无效.用一个例子来澄清
[OperationBehavior(TransactionScopeRequired = true)]
public async Task CallAsync()
{
await WriteAsync();
// Transaction.Current is now null
await WriteAsync();
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个Message Inspector,实现了IDispatchMessageInspector并将其作为服务行为附加,代码执行并且没有任何问题,但它与在service方法中声明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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过在调试时查看标识符,我可以看到它实际上是在消息检查器中与在服务中但 在第一次调用之后相同的事务,即
await _service_WriteAsync();
Run Code Online (Sandbox Code Playgroud)
Transaction.Current变为null.如果没有从消息检查器中的OperationContext.Current获取当前事务,那么同样的事情也是不可能的.
是否有可能实现这一目标?似乎唯一的方法是在服务方法中声明TransactionScope,即:
public async Task CallAsync()
{
var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
await _service.WriteAsync();
await _service.WriteAsync();
scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
如果transaction.current在中间变为null,那么使用以下服务契约显然会在第二个服务调用上获得异常
[OperationContract, TransactionFlow(TransactionFlowOption.Mandatory)]
Task WriteAsync();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
693 次 |
| 最近记录: |