我的一个WCF服务操作已启用事务 -
[OperationBehavior(TransactionScopeRequired = true)]
public Car UpdateCar(Car c)
{
}
之前,我使用InstanceContextMode作为PerCall和ConcurrencyMode作为Multiple运行此服务,这让我得到以下错误 -
System.ServiceModel.dll中发生未处理的“System.InvalidOperationException”类型异常 附加信息:'InventoryManager'服务配置为ReleaseServiceInstanceOnTransactionComplete设置为true,但ConcurrencyMode未设置为Single。 ReleaseServiceInstanceOnTransactionComplete需要使用ConcurrencyMode.Single。
为了解决上述错误,我将'ReleaseServiceInstanceOnTransactionComplete'设置为false,这就行了。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall
, ConcurrencyMode = ConcurrencyMode.Multiple
, ReleaseServiceInstanceOnTransactionComplete = false)]
有人可以帮助理解如何使用'PerCall'处理服务实例和'Multiple'案例解决了这个问题。如果我发布服务实例,WCF会怎么想。
答案 0 :(得分:0)
这些是由WCF设计师做出的纯粹设计决策。
从编写WCF服务的书中:
WCF架构师不相信开发人员在面对事务时正确管理其会话服务的状态。因此,他们决定将会话事务服务视为每次调用服务,以强制执行适当的状态感知编程模型。
使用ConcurrencyMode.Multiple的Percall服务当然没用。在服务加载时,WCF验证当ReleaseServiceOnTransactionComplete为true时,如果TransactionScopeRequired对于至少一个操作为真,则ConcurrencyMode为ConcurrencyMode.Single。 这就是你正在观察的行为。
设计人员可能正确决定让WCF在交易中处理并发。在服务中很难管理自己的并发。
例如,我有一项服务也充当了另一项服务的客户。
将并发模式更改为Multiple时,服务有时会在尝试打开客户端连接时抛出异常:
“System.InvalidOperationException:无法在此频道上进行呼叫,因为正在调用Open()。”
这是设计师想要避免的那种难以调试的错误(我认为)
答案 1 :(得分:0)
服务的默认实现是
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
如果在您的服务实现的任何操作上定义了TransactionScope:
[OperationBehavior(TransactionScopeRequired = true)]
public void Method() { }
默认的Service实现将被放置到
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
此属性将阻止它并重新获得您的PerSession语义:
[ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete = false)]
请注意,如果您具有会话式服务并且在一项操作中至少拥有一个TransactionScopeRequired = True
,则这是必需的。