跨多个HTTP请求拆分的多步数据库事务

7

我以前在桌面客户端应用程序中使用TransactionScope来回滚不完整的多步事务。但这种方法似乎不适用于Web应用程序。

请问是否有任何建议,可以确保如果整个过程未完成,则跨越几个页面的多个步骤可以被回滚?(例如,他们的浏览器崩溃或他们在中途关闭浏览器)

当然,我可以将内容写入某些临时表,然后在单个事务中将最终记录传输到真实表,但这会存在竞争条件的风险。我想开始一个事务,提供几个页面,每个页面向表中写入事务的一部分,然后通过提交完成事务,如果事务没有完成,则在会话结束时回滚它。

或者我考虑得不对? 有什么建议吗?

由于我正在使用MVC 3、EF 4.1和Ninject,我不确定这会对解决方案产生什么影响,但我想包括这些信息。

2个回答

8

在多个页面之间没有数据库事务/TransactionScope。即使尝试这样做也是非常错误的。

您有两个选项来解决问题:

  • 使用Session

    将数据存储在会话中,仅当用户完成所有步骤并确认保存时才将其持久化到数据库中。这绝对是您需要的。

  • 使用工作流基础和长时间运行的事务。

    长时间运行的事务不是数据库事务-它们是完全自定义的解决方案,您必须手动实现补偿(回滚长时间运行的事务)。您仍然必须以某种方式检测到您的工作流应该进行补偿,但这对于您的解决方案并非必要。它适用于需要多个会话的“事务”的解决方案。


这意味着你必须手动处理并发。对我来说,这似乎是一种代码异味。 - Erik Funkenbusch
在Web应用程序中手动处理并发是很常见的。数据库事务应该尽可能短 - 在大多数常见情况下仅为几分之一秒。如果您想要做的意味着在数据库中进行数分钟的密集锁定,则应用程序的性能将变得非常糟糕。 - Ladislav Mrnka

1

您可以考虑使用nservicebus或者masstransit来设置并使用他们的saga功能。


使用服务总线似乎是多余的,因为我还在使用一个能够进行服务定位的IoC容器。 - Erik Funkenbusch
3
这句话的意思是:这没有意义。服务总线和控制反转非常不同。Sagas可以消除竞态条件,允许非常明确的状态转换(消息)。但是,您可能只需使用临时表就可以解决问题。 - Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接