使存储库依赖于另一个存储库

MrG*_*mpy 29 c# repository-pattern solid-principles

我最近花了很多时间阅读SOLID原则并决定了解我使用的代码库是如何比较的.

在我们的一些代码中有一个存储库(存储库A).当要从存储库A中删除记录时,我们还需要从存储库B中删除关联的记录.因此,原始编码器创建了对存储库B的具体实现的依赖性.存储库A中的方法在事务中并且从存储库A中删除记录,然后调用存储库B上的方法以删除关联的数据.

我对S原理的理解是每个对象应该只有一个改变的理由,但是对于我的存储库A有2个理由要改变?还是我离开了标记?

Ser*_*kiy 54

存储库应该承担单一责任 - 坚持一种实体.例如员工.如果必须从其他存储库中删除一些关联的记录,它看起来像业务逻辑.例如

当员工被解雇时,我们应该删除他的工作日志

而业务逻辑的通常位置是域服务.这项服务将拥有两个存储库并完成所有工作:

staffService.Fire(employee)
Run Code Online (Sandbox Code Playgroud)

实施看起来像

public class StaffService
{
    private IEmployeeRepository employeeRepository;
    private IWorkLogRepository workLogRepository;
    private IUnitOfWorkFactory uowFactory;

    // inject dependencies

    public void Fire(Employee employee)
    {
        using(var uow = uowFactory.SartNew())
        {
            workLogRepository.DeleteByEmployee(employee.Id);
            employeeRepository.Delete(employee.Id);
            uow.Commit();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,基本建议

  • 尝试将您的业务逻辑保存在一个地方,不要将其部分传播到UI,部分存储到存储库,部分传输到数据库(有时由于性能问题,您必须在数据库端执行某些逻辑,但这是一个例外)
  • 永远不要让存储库引用其他存储库,存储库是应用程序的一个非常低级的组件,其职责非常简单

如果您有员工并且它有一些存储在不同数据库表中的嵌套对象,您可能想知道该怎么做.如果您将该对象与员工分开使用,那么一切都如上所述 - 您应该有单独的存储库,以及一些操作这两个存储库的其他对象(服务).但是,如果您不将该嵌套对象与员工分开使用,那么员工是一个聚合根,您应该只有员工存储库,它将查询其中的两个表.

  • 存储库不应该引用另一个存储库?也许,但是假设我有ClassA总是需要一个嵌套的ClassB(需要工作),但ClassB对象本身可以单独工作.当我的服务从repositoryA检索ClassA对象时,此存储库需要使用repositoryB来检索objB并将其分配给objA(使用工厂),如下所示:`class RepositoryA {public ClassA GetById(string id){objB = repositoryB.GetById (IDB); factory.CreateObjA(idA,objB); `如何避免存储库之间的引用? (9认同)
  • @Jonathan我不认为在其他存储库中使用存储库来正确构建域实体有什么问题。例如,如果您有一个没有会议类型实体就无法构建的会议实体,那么会议存储库使用 MeetingType 存储库就完全没问题。事实上,这仍然保持隔离,并且可以避免代码重复。 (3认同)