我写了一堂课来协助添加&使用核心服务将目标删除到发布目标。目标通常通过核心服务公开为一个字符串(带有XML内容),所以我写了我自己的包装器等等。
我现在遇到需要更新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.Dispose()
之前中断并检查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();
}
基本上,这就是问题:我必须做些什么来为我的.Save()方法添加事务性?
我试过这样做:
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
public void Save()
{
_client.Save(targetData, readOptions);
}
但它并没有什么不同。有没有办法确定我目前是否在交易中并以某种方式“使用”该交易?我不想要一个交易,只想拥有一个操作选项。
谢谢,很抱歉很长的帖子...想确保我提供尽可能多的信息。
答案 0 :(得分:3)
最好的资源是:WCF Transaction Propagation
您至少缺少一步。您还需要在绑定中启用事务:
<bindings>
<netTcpBinding>
<binding name = “TransactionalTCP” transactionFlow = “true” />
</netTcpBinding>
</bindings>
有没有办法确定我目前是否在交易中 以某种方式“使用”那笔交易?
是。要确定您是否在事务中,可以检查Transaction.Current。如果您正在进行交易,除非您明确选择退出,否则您将使用它。这是关于环境交易的美丽/可怕的事情。
WCF Transaction Propagation中的图5:
class MyService : IMyContract
{
[OperationBehavior(TransactionScopeRequired = true)]
public void MyMethod(...)
{
Transaction transaction = Transaction.Current;
Debug.Assert(transaction.TransactionInformation.
DistributedIdentifier != Guid.Empty);
}
}
如果Transaction.Current.TransactionInformation.DistributedIdentifier为空,则该事务是本地的,并且没有“流动”。请注意,在TransactionFlowOptions.Allowed
配置中,如果事务无法流动,则会以静默方式失败。因此,这确实是唯一可以检查的方法......并且不会比您预期的更容易发生流动。
当我使用生产服务的转换时,我实际上避免使用TransactionFlowOptions.Allowed
,因为调用者从未确定事务是否实际流过。如果部署中存在绑定配置错误,一切都会正常运行但回滚会失败...这是一个非常容易检测的错误。所以我切换到了必需品。然后调用者可以确保他们提供的事务实际成功传递。 (如果事务不在TransactionFlowOptions.Required
配置中流动,您将获得异常。)