如何在 WCF 中同时实现会话和事务流
本文关键字:会话 实现 事务 WCF | 更新日期: 2023-09-27 18:35:14
在尝试回答问题时,很明显,我和 OP 都无法同时构建一个既Session
又TransactionFlow
启用的 WCF 服务 - 我能提供的唯一解决方案是删除TransactionFlow
以使 WCF 会话实例化正常工作。
尽管从逻辑上讲,会话持续时间可以想象超过事务(请记住,TransactionFlow
可能意味着事务持有宝贵的服务器资源,如数据库锁、消息队列和事务文件系统),但我找不到明确的参考来确认或拒绝同时实现这两个功能的可能性。
所以我的问题是:如何让InstanceContextMode=InstanceContextMode.PerSession
和TransactionFlow
在 WCF 中同时工作?
尝试了什么:
ITransactionService.cs
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ITransactionService
{
[OperationContract(IsInitiating = true, IsTerminating = false)]
[TransactionFlow(TransactionFlowOption.Mandatory)]
int Start(int userId);
[OperationContract(IsInitiating = false, IsTerminating = true)]
[TransactionFlow(TransactionFlowOption.Mandatory)]
int Finish(int userId);
}
TransactionService.svc.cs
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class TransactionService : ITransactionService
{
public int count = 0;
[OperationBehavior(TransactionScopeRequired = true)]
public int Start(int userId)
{
Debug.Assert(Transaction.Current != null, "No Transaction!");
count = count + 1;
return count;
}
[OperationBehavior(TransactionScopeRequired = true)]
public int Finish(int userId)
{
Debug.Assert(Transaction.Current != null, "No Transaction!");
Debug.Assert(count > 0, "No Session!");
return count;
}
客户端.cs
using (var ts = new TransactionScope())
using (var svc = new TransactionServiceClient())
{
svc.Start(0);
svc.Finish(0);
ts.Complete();
}
Service web.config
<services>
<service name="WcfLibrary1.TransactionService">
<endpoint address="" binding="wsHttpBinding"
contract="WcfLibrary1.ITransactionService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding transactionFlow="true"/>
</wsHttpBinding>
</bindings>
<protocolMapping>
<remove scheme="http" />
<add scheme="http" binding="wsHttpBinding" bindingConfiguration="transactionFlowEnabled"/>
</protocolMapping>
客户端网络.config
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ITransactionService" transactionFlow="true" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:65171/TransactionService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITransactionService"
contract="TransactionService.ITransactionService" name="WSHttpBinding_ITransactionService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
经过一些试验和错误,这似乎是可能的。问题似乎是TransactionFlow
的默认行为应用以下默认设置:
- 在类的服务行为属性上 -
ReleaseServiceInstanceOnTransactionComplete = true
- 在方法的操作协定属性上 -
TransactionAutoComplete = true
当它们相互结合使用时,将导致释放服务的实例,从而破坏现有会话中保留的任何状态。
禁用以下任一选项将使服务实例在会话期间保持活动状态,从而允许同时使用TransactionFlow
和Session
:
即在ServiceContract
:
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ITransactionService
{
[OperationContract(IsInitiating = true, IsTerminating = false)]
[TransactionFlow(TransactionFlowOption.Mandatory)]
int Start(int userId);
[OperationContract(IsInitiating = false, IsTerminating = true)]
[TransactionFlow(TransactionFlowOption.Mandatory)]
int Finish(int userId);
}
在服务类上更改此项:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
ReleaseServiceInstanceOnTransactionComplete = false)]
public class TransactionService : ITransactionService
{
或者,在操作上:
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = false)]
public int Start(int userId)
{