Workflow FoundationExternalDataExchange 消息已排队且具有事务性?
我最近一直在 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() 中提交到数据库的数据如何回滚,但向前推进的工作流程可能会很糟糕。
任何人都可以确认这一点吗?如果是的话,您是否有解决方法使该消息成为事务性消息?
我真正想要的是这两件事之一:
- 工作流不应该对我通过外部数据交换排队的消息做出反应,直到提交消息排队的事务(就像 SQL Server 中的服务代理所做的那样)。
--或者--
- 如果工作流确实开始对我交付的事件起作用,它也应该回滚。 不过,我不明白使用默认调度程序如何会发生这种情况。 我希望工作流程执行保持异步,因此如果不需要,我不想切换调度程序。
I've been working with some ExternalDataExchange - based communication in WF recently. My understanding is that when working with a long-running (in this case, a State Machine) workflows, communication is queued, durable, and transactional.
I'm using SQL Persistence and a EventArgs that is marked as "WaitForIdle = true".
I would assume that when I do something like this:
using(TransactionScope scope = new TransactionScope())
{
IMyEDEService service = wfRuntime.GetService<IMyEDEService>()
service.MyMethod(wfInstanceGuid, "Here's some data");
DoSomeDatabaseWork();
} //Dispose causes scope to rollback
I would expect that my event won't fire on the workflow. It appears to actually be delivered, though, so this leads me to believe this is not transactional. You could see how the data committed to a database in DoSomeDatabaseWork() being rolled back, but the workflow moving foward could be bad.
Can anyone confirm this and if so, do you have a workaround to make the message a transactional one?
Really what I want is one of these two things:
- The workflow shouldn't react to the message I enqueued via external data exchange until the transaction that enqueued the message is committed (much like service broker does in SQL server).
--or--
- If the workflow does start acting on the event I delivered, it should rollback as well. I don't see how this could occur using the default scheduler, though. I'd like the workflow execution to remain asynchronous, so I don't want to switch out the scheduler if I don't have to.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里有几个问题。 首先,当您使用 SQL 持久性时,通知事件工作流并让工作流发布事件是持久且异步的,并且工作流的底层管道是事务性的......但不是您想象的那样。
如果事件序列中的某个地方发生了可怕的事情,最终导致您的工作流程转换到新状态,那么工作流程将恢复到尝试该活动之前的状态 - 这使工作流程保持一致的状态,因为“国家之间”是个坏主意。
像上面那样使用事务作用域是可以的,但是您必须记住,事务作用域真正起作用的唯一时间是当 using 块中的类知道事务作用域时。
您可以做的是将“MyMethod”的调用包装在 try/catch 块中。 当出现问题时,您可以投票支持回滚...但这仍然不会“取消调用”您的 EDES 上的方法。
如果您可以提供一些关于您想要在更高级别上完成的任务的具体信息,那么 WF 固有的一些东西可能比试图将事务范围强加到组合中更适合您。
编辑
我做了一些挖掘,发现了几个不同的地方,我们被告知没有 API 来操作调度程序工作队列。 不幸的是,对我们来说,这意味着我们想要的任何类型的回滚行为都必须自己手动实现。
如果我更多地了解您为什么尝试回滚通过 EDES 排队的工作,我也许能够建议一些潜在的架构来完成您的任务,而无需重新发明轮子(事务)。
当我遇到这样的问题时,十分之九,看起来 WF 不支持我想要做的事情,问题是因为我在外部保留了太多代码工作流程或试图在其中放入太多代码,并且重构我的工作完成位置通常可以解决我的问题,而不需要我编写新的东西。
There's a couple of issues going on here. First, when you are using SQL persistence, notifying the workflow of events and having the workflow publish events is persistent and asynchronous and the underlying plumbing of the workflow is transactional...but not in the way you might think.
If something horrible happens somewhere in the sequence of events that will eventually cause your workflow to transition to a new state, then the workflow will revert to the state it was in before attempting the activity - this keeps the workflow in a consistent state since being "between states" is a bad idea.
Using a transaction scope as you've done above is fine, but you have to remember that the only time transaction scopes actually work is when the classes within the using block are aware of the the transaction scope.
What you can do is have your call to "MyMethod" wrap things in a try/catch block. When something goes wrong, you can vote for a rollback... but this still doesn't "un-invoke" the method on your EDES.
If you can give some specifics about what you're trying to accomplish at a higher level, there may be some things intrinsic to the WF that might better suit you than trying to shoehorn a transaction scope into the mix.
Edit
I did some digging and found a couple of different places where we are told that there is no API to manipulate the scheduler work queue. Unfortunately for us what this means is that any sort of rollback behavior that we want we're going to have to implement by hand on our own.
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.