Entity framework 应该将应用程序服务注入域服务吗

Entity framework 应该将应用程序服务注入域服务吗,entity-framework,dependency-injection,domain-driven-design,application-layer,business-layer,Entity Framework,Dependency Injection,Domain Driven Design,Application Layer,Business Layer,我正在使用Entity Framework 6开发一个WinForms应用程序,该应用程序具有以下层: 介绍 应用 领域 基础设施 当用户从UI单击save按钮时,它调用应用层中的应用程序服务并传入请求。然后,应用程序服务使用请求调用域服务。域服务调用域模型中的多个实体来对请求中使用的数据执行验证 域模型中的一个或多个验证需要来自存储库的信息,以确定从表示层接收的请求中的数据是否符合某些业务规则 我正在考虑两个方案来解决这个问题 让应用程序服务从中检索所需的信息 存储库进行验证,并将这些值传

我正在使用Entity Framework 6开发一个WinForms应用程序,该应用程序具有以下层:

  • 介绍
  • 应用
  • 领域
  • 基础设施
当用户从UI单击save按钮时,它调用应用层中的应用程序服务并传入请求。然后,应用程序服务使用请求调用域服务。域服务调用域模型中的多个实体来对请求中使用的数据执行验证

域模型中的一个或多个验证需要来自存储库的信息,以确定从表示层接收的请求中的数据是否符合某些业务规则

我正在考虑两个方案来解决这个问题

  • 让应用程序服务从中检索所需的信息 存储库进行验证,并将这些值传递到 域服务,它将调用域模型和实体 验证规则和值的传入请求。那就让 应用程序服务在域服务启动时保存请求 已完成验证,这将导致返回控件 返回同步等待的应用程序服务 完成验证。如果我这样做,那么域层将 没有对存储库的直接或间接(注入)引用。 如果我这样做,域服务的单元测试将更容易 因为没有注入任何东西来执行验证。 它所需要的一切都已经传递进来了。缺点是有些 业务知识被放到应用程序服务中,因为现在 它需要知道要检索哪些存储库信息 请求的验证

  • 调用域服务以验证请求时, 将应用程序服务的实例注入其中。领域 然后,服务可以使用 注入的应用程序服务,其服务契约在中定义 域层。一旦所有信息都可用,它就会被传递 根据需要向不同的实体验证规则和值。一旦 验证完成后,域服务将使用 注入的应用程序服务。当域服务完成时 和退出时,它将保存操作的状态返回给 正在等待验证的应用程序服务 完成然后,外部等待应用程序服务可以返回 保存到UI的结果。我在这里关心的一个问题是 对域服务进行单元测试我将不得不模拟注入的 应用服务

  • 哪种选择或其他行动方案效果更好?提前谢谢

    “是否应将应用程序服务注入域服务”

    不,从来没有

    从应用程序服务解析数据并将其传递给域服务通常是好的,但是如果您认为域逻辑正在泄漏,那么 您可以应用接口隔离原则(ISP),并根据查询“所需数据”所需的合同在域中定义接口。在存储库或任何其他能够完成任务的对象上实现该接口,并将其注入域服务

    例如(伪代码)

    编辑:

    我有一个带有员工姓名的请求聚合根。一条规则是 员工必须是全职而非承包商

    如果用于执行验证的信息已存在于聚合上,则您也可以将此AR用作其他AR的工厂。假设员工持有其合同类型

    Employee employee = employeeRepository.findById(employeeId);
    Request request = employee.submitRequest(requestDetails); //throws if not full time
    requestRepository.add(request);
    
    请注意,除非更改聚合边界,否则此处只能使不变量最终一致,但其他解决方案也是如此

    “是否应将应用程序服务注入域服务”

    不,从来没有

    从应用程序服务解析数据并将其传递给域服务通常是好的,但是如果您认为域逻辑正在泄漏,那么 您可以应用接口隔离原则(ISP),并根据查询“所需数据”所需的合同在域中定义接口。在存储库或任何其他能够完成任务的对象上实现该接口,并将其注入域服务

    例如(伪代码)

    编辑:

    我有一个带有员工姓名的请求聚合根。一条规则是 员工必须是全职而非承包商

    如果用于执行验证的信息已存在于聚合上,则您也可以将此AR用作其他AR的工厂。假设员工持有其合同类型

    Employee employee = employeeRepository.findById(employeeId);
    Request request = employee.submitRequest(requestDetails); //throws if not full time
    requestRepository.add(request);
    
    请注意,除非更改聚合边界,否则此处只能使不变量最终一致,但其他解决方案也是如此

    当域中的重要流程或转换不是实体或值对象的自然职责时,将操作作为声明为服务的独立接口添加到模型中。根据模型的语言定义接口,并确保操作名称是通用语言的一部分。使服务无状态-埃文斯,蓝皮书

    不要过分倾向于将领域概念建模为服务。只有在情况合适时才这样做。如果我们不小心,我们可能会开始将服务视为我们的建模“银弹”。过度使用服务通常会导致创建一个单一的域模型的负面后果,其中所有的域逻辑都驻留在服务中。-弗农,红皮书

    我试图通过大量引用来说明的是,您似乎认为域服务是您必须拥有的,而您完全不必这样做。您的应用程序服务可以愉快地使用存储库获取聚合,然后调用聚合根方法来执行必要的操作。哟