C# 服务层与存储库的关系

C# 服务层与存储库的关系,c#,service,repository,domain-driven-design,repository-pattern,C#,Service,Repository,Domain Driven Design,Repository Pattern,什么更有意义。有一个服务层引用多个存储库(充当门面),或者有一个存储库将多个相关实体组合在一起。例如,我有以下实体,但我不确定如何组织 实体(POCO) 调查 调查组 调查问题 调查者 Q1.这些实体中的每一个都应该有自己的职责吗?SurveyQuestion不存在于SurveyGroup中,SurveyGroup不存在于SurveyGroup中 第二季度。我是否应该为调查、调查组和调查问题创建一个存储库,并为调查者和回答者创建另一个存储库 Q3.我是否应该为每个存储库创建一个单独的存储库,并创

什么更有意义。有一个服务层引用多个存储库(充当门面),或者有一个存储库将多个相关实体组合在一起。例如,我有以下实体,但我不确定如何组织

实体(POCO)

  • 调查
  • 调查组
  • 调查问题
  • 调查者
  • Q1.这些实体中的每一个都应该有自己的职责吗?SurveyQuestion不存在于SurveyGroup中,SurveyGroup不存在于SurveyGroup中

    第二季度。我是否应该为调查、调查组和调查问题创建一个存储库,并为调查者和回答者创建另一个存储库

    Q3.我是否应该为每个存储库创建一个单独的存储库,并创建一个引用它们的服务类(SurveyService)


    我不确定这类东西的“最佳实践”是什么。

    DDD中的一般经验法则是为每个对象创建一个存储库

    在您的示例中,看起来
    Survey
    将是聚合根,因此创建
    SurveyRepository
    经验法则(即标准)是为具有标识(例如主键)的实体建立存储库。换句话说,这些实体可以[至少]在自己的存储库中定义CRUD操作

    对于不是“一流”实体且不能单独定义CRUD的实体,存储库不是必需的。因此,必须使用依赖关系映射来处理它们(其他“一流”实体映射负责处理它们)

    但是,您可能希望减少项目中存储库的数量,这时您就开始寻找其他(非标准)方法来对实体进行分组

    结论:如果您想成为标准的,那么就拥有尽可能多的自包含实体的存储库。具体答案取决于您问题中列出的实体,我认为您将能够根据手头的这些信息自行判断

    前面的答案[理论上]可能会导致存储库不必要地处理多个实体,以及将来查找/定位实体处理/映射代码的麻烦


    [我使用了Fowler,M.-identity,dependency mapping定义的术语]

    如果您的存储库处理了一些不必要的事情,那么您可能错误地定义了聚合边界。存储库应该只用于获取和持久化整个聚合,这些聚合定义并强制实现域的一致性——它的不变量。使实体的存储库不是聚合根将导致违反不变量。聚合根是时间的函数,具有不断变化的树/复合结构,特别是在开发过程中需求发生变化时。跟上这种变化的性质意味着改变存储库并跟踪代码中的实现位置。此外,如果聚合根存储库与其他存储库交互以构造聚合,则从域中获取聚合看起来是相同的。出于这一目的,您不需要只为聚合根设置存储库。您谈论的是DAO,而不是存储库。你完全没有抓住后者的重点。当然,一个存储库可以使用多个DAO来组成聚合。这一点很好!但不是,我说的是存储库实现。如果预见到DAO的变化,存储库通常来自抽象工厂,因此存储库通常具有创建存储库的工厂引用。我建议将支持标识映射的实体的存储库分开,但仍将依赖关系映射分组到同一存储库中。另一方面,DAO将分别具有“一级”(标识映射)和“二级”(依赖映射)实体。换句话说,我建议使用稍微不同的分组,或者可能使用不同的方法来识别聚合。