【发布时间】:2018-11-05 16:52:21
【问题描述】:
在 DDD 的上下文中,当您处理域事件时,事务应该在哪里开始和结束?
Infrastructure.Layer 有 UoW 实现
/// => configured via DI as Per Request
class UnitOfWork : IUnitOfWork
{
ITransaction _transaction;
static ISessionFactory _factory;
ISession _session
UnitOfWork()
{
_session = _factory.OpenSession();
_transaction = _session.BeginTransaction(); ///=> start transaction
}
void Commit()
{
try
_transaction.Commit();
catch
_transaction.Rollback();
finally
Dispose();
}
}
Application.Layer 用例处理程序
class SomeAppServiceUseCaseHandler : IUseCaseHandler
{
IUnitOfWork _uow;
ISomeRepo _repo;
AppService(IUnitOfWork uow, ISomeRepo repo)
{
_uow = uow;
_repo = repo;
}
void UseCaseHandler(Request request)
{
SomeAggregate agg = _repo.GetAggregate(request.Id)
agg.DoSomethingToChangeState();
_repo.UpdateAgg(agg);
_uow.Commit(agg); ///=> commit changes for this transaction success
}
}
并且在 Domain.Layer 中,该方法还将 Domain.Event 添加到聚合的域事件列表中。
SomeAggregate : AggregateRoot
{
DoSomethingToChangeState()
{
.... do something
var someObject;
base.AddEvent(new SomethingHappenedEvent(someObject)));
}
}
Application.Layer 具有 Domain.Event 处理程序
class SomethingHappenedEventHander : Handler<SomethingHappenedEvent>
{
IRepo repo;
IUnitOfWork _uow;
DomainEventHander(IRepo repo, IUnitOfWork uow)
{
_repo = repo;
_uow= uow;
}
HandleEvent(someObject)
{
AnotherAggregate agg = new AnotherAggregate ();
agg.DoSomeCommand(someObject);
_repo.Create(agg);
_uow.Commit(); ///=> commit changes for same transaction fail, should rollback prev transaction as well
}
}
我觉得这不对
-
谁应该发布活动?从我所见,UoW 应该在 Commit() 方法中这样做,但我认为这是不对的,我认为 UoW 不应该这样做,但我看不出还有谁可以。
如果在链中的某个点出现故障,我已经提交了一些数据,如果沿途出现故障,我很可能不想这样做。
那么这两种情况应该如何正确处理呢?
【问题讨论】:
-
DDD 规定每个事务只能修改一个聚合。
-
是的,确实如此,但是应该如何处理多个聚合更新呢?我认为我不应该在 Application.Layer UseCaseHandler 中开始事务
-
在 Saga/流程管理器中。如果您需要回滚聚合,则边界有问题,或者您需要将其建模为业务流程
标签: architecture transactions domain-driven-design software-design unit-of-work