我必须发送电子邮件,写入文件,然后调用Web服务。为了保持一致性,必须执行所有步骤。如果任何步骤抛出异常或错误,则必须回滚所有步骤。
在我开始使用自己的对象ACID引擎之前,是否有在对象级别实现ACID语义的常用模式?
更好的是,我可以在.NET平台上使用任何现有的库吗?
编辑:我知道发送电子邮件无法撤消,但无法连接到SMTP服务器会导致终止整个事务。此外,我希望这可以扩展用于将来的行动。
答案 0 :(得分:5)
几年前我最后一次看到这样的事情。我记得的一点是,它使用命令模式并将每个命令对象存储在队列中。我认为这是一个LIFO堆栈。
因此,如果“事务”失败,引擎将弹出命令对象,撤消命令,然后销毁命令对象。重复直到堆栈为空。如果“交易”成功,堆栈就会被清除。
不幸的是,我不记得更多。
CSLA.NET实现了类似的撤销堆栈。这是代码的唯一例子,我可以从头脑中思考。
答案 1 :(得分:3)
当ACID语义可能不合适时,Windows Workflow Foundation有一个概念compensation(使用Composite活动)。当然,它也支持ACID事务。
一个好问题是为什么要打扰 补偿?不是一个大的ACID 具有自动回滚的事务 一样好吗? ACID交易是 操作发生时最合适 在同一个数据库内或在 相同的信息系统。也是 操作结束时最合适 很快。当不同的公司和 涉及服务,定义 根据ACID语义进行处理 经常充满挑战。对于它 隔离和耐用,你必须保持 不同公司的所有资源 在任务期间锁定。 这通常是不合理的, 特别是如果任务很长。为了它 为了保持一致和原子,你需要 临时补偿代码。
答案 2 :(得分:3)
不依赖外部库的最简单技术是prevalence。定期 checkpoint 使用序列化来拍摄状态的快照,然后通过序列化有关数据的每个副作用操作的足够信息来维护日记,以便稍后重复。如果出现问题,请重新加载最新的检查点,然后重新应用该点之后写的所有日志记录。
对于更复杂的内容,请尝试software transactional memory。在当前语言中实现可能有些笨拙,但功能非常强大,并且可能会为您提供一些额外的并发技术。
对于访问Web服务或发送电子邮件等不可逆转的操作,您需要使用compensating transactions:拨打另一个Web服务来取消或更新上一个的结果,或者发送另一封电子邮件通知收件人认为事情没有按预期发挥作用。
答案 3 :(得分:1)
由于您无法取消发送电子邮件,并且编写文件相对便宜,我只是按照正确的顺序执行这些操作:
答案 4 :(得分:1)
一个想法是使用JMS作为“引擎”,您可以利用JMS事务(可以加入现有事务,例如DB事务)。这开始导致异步事件驱动的体系结构,除非我们讨论简单的应用程序,否则这可能是一件好事 - 在这种情况下,您可能不需要提出问题。
这方面的一个例子是简单的帐户创建。为此,您希望将帐户信息保存到数据库,并向用户发送电子邮件以进行激活 - 但出于显而易见的原因,您希望将它们放在同一个事务中。
您不应该在交易中放置电子邮件发送代码,因为即使您可能发送电子邮件 - 数据库事务提交可能由于某种原因而失败。 您也不应该将电子邮件发送到交易之外(提交后),因为电子邮件发送可能会导致孤立帐户失败。
所以在这种情况下使用JMS - 让JMS在数据库事务中发送代码并让它加入该事务。保证邮件传递。在另一端有消耗队列发送电子邮件的东西。如果电子邮件发送失败,最好的选择是记录/发出警报 - JMS将回滚并将消息放回队列中供以后使用。即,一旦你有希望解决问题,尝试重新发送电子邮件。
关键是 - 数据库记录是一致的,最终会发送电子邮件。
答案 5 :(得分:0)
两个想法:
答案 6 :(得分:0)
此外,最近发布了一个实验项目STM .NET。这个项目为C#增加了事务内存。它实际上修改了CLR以支持这一点。