提问者:小点点

如何使用CoreService在自定义类上实现WCF事务支持?


我写了一个类来辅助添加

我现在遇到了需要更新2个发布目标的情况,并认为使用事务范围来确保两个目标同时更新会很酷。

然而,我正在努力实现这一点。

代码工作(使用标准CoreService WCF客户端):

TransactionOptions txOptions = new TransactionOptions 
                    { IsolationLevel = IsolationLevel.ReadCommitted };
using(TransactionScope scope = new TransactionScope(
                            TransactionScopeOption.Required, txOptions))
{
    PublicationTargetData publicationTarget1 = (PublicationTargetData)client.Read("tcm:0-1-65537", readOptions);
    PublicationTargetData publicationTarget2 = (PublicationTargetData)client.Read("tcm:0-2-65537", readOptions);

    publicationTarget1.TargetLanguage = "JSP";
    publicationTarget2.TargetLanguage = "JSP";
    client.Save(publicationTarget1, readOptions);
    client.Save(publicationTarget2, readOptions);

    // Stop saving
    scope.Dispose();
}

执行此代码将成功回滚我所做的更改(如果我在scope. Dispos()之前中断并检查Tridion中的发布目标,它会成功更改目标,然后“撤消”更改)。

如果我现在尝试在事务中也使用我的“扩展发布目标”类,我将无法处置它。

TransactionOptions options = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted };
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
{
    ExtendedPublicationTarget target1 = new ExtendedPublicationTarget("tcm:0-1-65537");
    ExtendedPublicationTarget target2 = new ExtendedPublicationTarget("tcm:0-2-65537");
    target1.Destinations.Add(target1.Destinations[0]);
    target2.Destinations.Add(target2.Destinations[0]);
    target1.Save();
    target2.Save();
    scope.Dispose();
}

所以基本上,这就是问题:我必须做什么才能将事务性添加到我的。保存()方法?

我尝试过这样做:

[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
public void Save()
{
    _client.Save(targetData, readOptions);
}

但这并没有什么不同。有没有办法确定我当前是否处于交易中,并以某种方式“使用”该交易?我不想要求交易,只想拥有在其中操作的选项。

谢谢,很抱歉很长的帖子…想确保我提供了尽可能多的信息。


共1个答案

匿名用户

最好的资源是:WCF事务传播

您至少缺少一步。您还需要在绑定中启用事务:

<bindings>
   <netTcpBinding>
      <binding name = “TransactionalTCP” transactionFlow = “true” />
   </netTcpBinding>
</bindings>

有没有办法确定我当前是否在交易中并以某种方式“使用”该交易?

是的。要确定您是否在事务中,您可以查看Transaction. Current。如果您在事务中,除非您明确选择退出,否则您将使用它。这就是环境事务的美丽/可怕之处。

WCF事务传播中的图5:

class MyService : IMyContract 
{
   [OperationBehavior(TransactionScopeRequired = true)]   
   public void MyMethod(...)
   {
      Transaction transaction = Transaction.Current;
      Debug.Assert(transaction.TransactionInformation.
                   DistributedIdentifier != Guid.Empty);
   } 
}

如果Transaction. Current.TransactionInformation.分布式标识符为空,则事务是本地的并且没有“流动”。请注意,在TransactionFlowOptions.允许的配置中,如果事务无法流动,它会静默失败。因此这确实是检查的唯一方法…并且不流动比您预期的更容易发生。

当我在生产服务中使用传输时,我实际上避免了TransactionFlowOptions。允许,因为调用者永远不确定事务是否真的流转。如果部署中存在绑定配置错误,一切都会正常运行,但回滚会失败…一个非常棘手的错误。所以我切换到必需的。然后调用者可以确保他们提供的事务实际上成功通过。(如果事务没有在TransactionFlowOptions。必需的配置中流动,你会得到一个异常。)