为什么服务行为'ReleaseServiceInstanceOnTransactionComplete = false'需要在启用的事务上使用'ConcurrencyMode.Multiple'

时间:2016-09-08 04:47:04

标签: wcf

我的一个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会怎么想。

2 个答案:

答案 0 :(得分:0)

这些是由WCF设计师做出的纯粹设计决策。

从编写WCF服务的书中:

WCF架构师不相信开发人员在面对事务时正确管理其会话服务的状态。因此,他们决定将会话事务服务视为每次调用服务,以强制执行适当的状态感知编程模型。

使用ConcurrencyMode.Multiple的Percall服务当然没用。在服务加载时,WCF验证当ReleaseServiceOnTransactionComplete为true时,如果TransactionScopeRequired对于至少一个操作为真,则ConcurrencyMode为ConcurrencyMode.Single。 这就是你正在观察的行为。

https://books.google.nl/books?id=PvNrurEhmiEC&pg=PA348&lpg=PA348&dq=per-session+transactional+services&source=bl&ots=CiDuKxG_Ox&sig=UvkgF1yTxmirsf_Zb452bW86AmQ&hl=nl&sa=X&ved=0ahUKEwiYjrX-uPrPAhWGfhoKHTgWBckQ6AEIHDAA#v=onepage&q=per-session%20transactional%20services&f=false

设计人员可能正确决定让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,则这是必需的。