3

我最近一直在 WF 中使用一些基于 ExternalDataExchange 的通信。我的理解是,当使用长时间运行的(在本例中为状态机)工作流时,通信是排队的、持久的和事务性的。

我正在使用 SQL Persistence 和一个标记为“WaitForIdle = true”的 EventArgs。

我会假设当我做这样的事情时:

using(TransactionScope scope = new TransactionScope())
{
     IMyEDEService service = wfRuntime.GetService<IMyEDEService>()
     service.MyMethod(wfInstanceGuid, "Here's some data");
     DoSomeDatabaseWork();
} //Dispose causes scope to rollback

我希望我的事件不会在工作流程中触发。不过,它似乎实际上已经交付,所以这让我相信这不是交易性的。您可以看到在 DoSomeDatabaseWork() 中提交到数据库的数据是如何回滚的,但是向前移动的工作流可能很糟糕。

任何人都可以确认这一点,如果是这样,您是否有解决方法使该消息成为事务性消息?

我真正想要的是以下两件事之一:

  1. 工作流不应该对我通过外部数据交换排队的消息做出反应,直到将消息入队的事务被提交(就像服务代理在 SQL Server 中所做的那样)。

- 或者 -

  1. 如果工作流确实开始对我交付的事件起作用,它也应该回滚。不过,我看不出使用默认调度程序是如何发生这种情况的。我希望工作流执行保持异步,所以如果不需要,我不想切换调度程序。
4

1 回答 1

2

这里有几个问题。首先,当您使用 SQL 持久性时,通知工作流事件并让工作流发布事件是持久的和异步的,并且工作流的底层管道是事务性的……但不是您可能想象的那样。

如果在事件序列中的某处发生了可怕的事情,最终导致您的工作流转换到新状态,那么工作流将恢复到尝试活动之前的状态 - 这使工作流保持一致状态,因为“国家之间”是一个坏主意。

如上所述使用事务范围很好,但您必须记住,事务范围实际工作的唯一时间是 using 块中的类知道事务范围。

你可以做的是让你对“MyMethod”的调用将东西包装在一个 try/catch 块中。当出现问题时,您可以投票支持回滚......但这仍然不会“取消调用”您 EDES 上的方法。

如果您可以详细说明您要在更高级别上完成的工作,那么 WF 固有的某些内容可能比尝试将事务范围塞进组合中更适合您。

编辑

我做了一些挖掘,发现了几个不同的地方,我们被告知没有 API 来操作调度程序工作队列。对我们来说不幸的是,这意味着我们想要的任何类型的回滚行为都必须自己手动实现。

If I knew more about why you were trying to rollback work queued through an EDES I might be able to suggest some potential architectures for accomplishing your task without re-inventing the wheel (transactions).

9 times out of 10 when I run into problems like this where it looks like WF just doesn't support what I'm trying to do, the problem is because I've either kept too much code outside the workflow or tried to put too much code into it and refactoring where my work is done often fixes my problem without requiring me to write new stuff.

于 2009-04-14T13:35:31.527 回答