1

我们正在编写一个 MVC 数据维护应用程序是一个更大项目的一部分。我们尝试使用领域驱动设计 DDD。在 SO 上已经有其他关于此的问题,例如这里这里这里。然而他们并没有完全回答我的问题。

由于数据库有 75​​5 个表,因此我们在数据层中也有有界上下文。因此,我们为业务、角色、产品、客户等创建了有界上下文。

我们遇到的问题是,在 MVC 应用程序中,我们有一个“初始设置”视图,它使用最终跨越多个有界上下文的 ViewModel(在 Entity Framework 6 中使用 IUnitOfWork 模式)。因此,该视图必须写入业务上下文和角色上下文。

域模型将在一个更大的 pbject 图中有一个Business模型和一个Address模型以及一些其他模型。

ViewModel是这两个和其他领域模型的扁平化简化模型:

public class InitialSetupViewModel
{
    string BusinessName{get;set;}
    string Street{get;set;}
    string Street2{get;set;}
    string State{get;set;}
    string ZIP{get;set;}
    ...
}

这个 ViewModel 应该映射到我们正在使用Automapper执行的域模型。

控制器获取注入的域服务:

public class SetupController : Controller
{
    private readonly IMaintenanceService service;

    public SetupController( IMaintenanceService maintenanceService = null )
     {
        service = maintenanceService;
    }

    public void Create(...????....)
    {
        service.CreateBusiness(..?.);
    }

}

问题:

  1. 服务无法知道InitialSetupViewModel,那么应该将什么传递给服务?

  2. 服务必须知道BusinessDbContextand RolesDbContext。所以我必须在两者上调用 SaveChanges(),这超出了拥有单个 IUnitOfWork 的目的。我是否必须创建另一个包含业务和角色实体的 UnitOfWork?

我认为将这两个 IUnitOfWorks 合并为一个只是为了使这个 MVC 视图工作是不合理的。但是解决方案是什么?

谢谢!

4

1 回答 1

1

对一个你不知道的领域有强烈的看法总是很困难,但在这里:

  1. 正如已经评论过的,Controller应该承担在视图和域模型、DTO 或您拥有的东西之间映射的责任。它可以将一个实例InitialSetupViewModel作为输入,但实现细节可能会有所不同。

  2. 确实,如果您发现自己需要打破有界上下文的边界,那么重构域可能是正确的选择。不过,只关注工作单元模式,我不太明白你的犹豫。

    跟踪所有需要在一个事务中同步的域对象是工作单元实现的责任。同一个域对象涉及多个不同的工作单元并没有什么奇怪的。这并不意味着当您处理另一种类型的聚合时,您应该将“较小”的工作单元实现组合成“较大”的实现,而是在一个工作单元中同时包含“角色”和“业务”,当然。

    这样做应该被你的视图所吸引,而是被你的域模型中的“真实”所吸引,而不是仅仅处理域对象的集合,你的域应该描述合适的聚合。

也许用单独的事务(工作单元)存储每个域对象甚至是可以的,即如果不需要同步它们 - 例如,如果(或者甚至可能希望)失败Business并没有停止Roles通过或反之亦然,它仍然可以反之亦然。实际上,我认为甚至可以争辩说,如果有界上下文实际上是正确定义的,那么应该就是这种情况。

我希望这些评论有所帮助。

Martin Fowler 谈工作单元聚合

于 2014-12-05T13:08:36.177 回答