【问题标题】:Unit of work/Transaction within an application service method?应用程序服务方法中的工作单元/事务?
【发布时间】:2014-01-29 22:44:48
【问题描述】:
我了解如何使用实体框架来实现一个工作单元,并且仅在执行完整单元后才提交更改,但我该如何更进一步呢?例如,以下需要在一个事务下全部发生
CreateUser(...)
{
//1.) New up user object
//2.) Add newly created object to database
//3.) Send Email
//4.) Commit transaction ( ensures email is successfully sent AND object is created in database, else transaction fails
}
我不太确定如何确保发送电子邮件和将用户保存在数据库中都发生在一个事务中。非常感谢任何建议
【问题讨论】:
标签:
c#
architecture
domain-driven-design
onion-architecture
hexagonal-architecture
【解决方案1】:
并非所有资源都是事务性的。电子邮件就是其中之一。因此,当其他资源在事务中失败时,不能期望发送电子邮件会回滚。
有一些替代解决方案:
1) 在最后一步调用非事务性资源。
就像您在创建用户示例中所做的那样。在这种情况下,所有业务约束都被检查并通过,失败的唯一原因是在现实世界中不经常发生的基础设施问题(仔细维护)。当基础设施发生故障时做出一些补偿。这可以自动或手动完成,取决于它发生的频率。例如,如果发送了电子邮件,但用户设置回滚,你可以告诉他/她你很抱歉(这很重要:P)但设置有问题,请重试。
2) 应用最终一致性
改用事务性资源来触发流程。例如,您可以使用消息传递(如果使用 2 阶段提交,则为全局事务)来通知发送电子邮件。
CreateUser(...)
{
//1.) New up user object
//2.) Add newly created object to database
//3.) Publish user setup event by messaging
//4.) Commit transaction ( ensures message is successfully sent AND object is created in database, else transaction fails
}
在任何情况下,故障和不一致都会或多或少地发生。您需要评估是否可以接受。