情况就是这样:
假设我有一个应用程序,其中存在两种实体类型:
>公司
>人
此外,Person通过Person.employer提及公司,该公司表示雇用的公司.
在我的应用程序中,我使用存储库将数据库操作与业务模型相关的服务分开:我有一个PersonRepository.findOne(id)方法来检索Person实体和一个CompanyRepository.findOne(id)方法来检索公司.到现在为止还挺好.
这就是两难:
现在,如果我调用PersonRepository.findOne(id)来获取Person实体,我还需要通过Person.employer属性将一个完全解析的公司包含在内 – 这就是我面临两个实现的困境两个选项都不是最理想的:
选项A)我的存储库中的冗余查询,但数据库往返次数较少:
在PersonRepository中,我可以构建一个选择用户并在单个查询中选择公司的查询 – 但是,公司的select表达式很难并包含一些连接以正确组装公司. CompanyRepository已经包含这个逻辑来选择公司并在UserRepository中重写它是多余的.因此,理想情况下,我只希望CompanyRepository处理公司选择逻辑,以避免必须在两个存储库中冗余地编写相同的查询表达式.
选项B):在没有查询代码冗余的情况下分离关注点,但代价是额外的db往返和repo-dependencies:
在PersonRepository中,我可以引用CompanyRepository来处理获取Company对象,然后我将此实体添加到PersonRepository中的Person.employer属性.通过这种方式,我保留了逻辑,以查询封装在CompanyRepository中的公司,通过该公司实现关注点的清晰分离.这样做的缺点是我进行了额外的数据库往返,因为两个独立的查询由两个存储库执行.
总的来说,处理这种困境的首选方法是什么?
另外,在ASP.NET Core和EF Core中处理这种情况的首选方法是什么?
编辑:为了避免基于意见的答案,我想强调:我不是在寻找上面提到的两个选项的优缺点,而是寻求一个集成两个选项的好部分的解决方案 – 因为也许我只是在错跟踪我列出的两个选项.我也很好,答案解释了为什么没有这样的综合解决方案,所以我可以睡得更好,继续前进.
最佳答案 要按ID检索公司,您需要阅读Person的数据,并从中获取公司ID.因此,如果您希望将公司查询逻辑保留在一个地方,您最终将获得两次往返 – 一次获取公司ID(以及一个人拥有的其他任何属性),另外一次获得公司本身.
您可以重用从DbDataReader创建公司的代码,但人员公司查询可能需要加入“转发”人员的companyId到公司查询,因此这些查询的文本必须不同.
如果将查询逻辑移动到存储过程中,您可以两种方式(一次往返,不重复查询).这样你的person_sp就会执行company_sp,并返回所有相关数据.如有必要,您的C#代码将能够使用reader.NextResult()获取多部分结果集.现在,公司ID的“切换”将发生在RDBMS方面,从而消除了第二次往返.但是,这种方法需要在RDBMS端维护存储过程,从而有效地将一些存储库逻辑从C#代码库中运出.