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

时间:2015-05-08 07:50:31

标签: c# repository-pattern solid-principles

我最近花了很多时间阅读SOLID原则并决定了解我使用的代码库的比较方式。

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

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

2 个答案:

答案 0 :(得分:46)

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

  

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

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

staffService.Fire(employee)

实施将如下所示

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();
        }
    }
}

所以,基本建议

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

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

答案 1 :(得分:-2)

在这种情况下,您应该使用event dispatcher模式。

RepoA 上执行删除操作后,您可以发送如下事件:

dispatch repositoryA.deleted(RecordA)

将保存已删除记录的信息。

然后,一个发泄池将订阅此类事件,并且将存储库B作为依赖关系将调用删除。

让我们使用B作为实体名称,监听器声明应该听起来像:

Listen RepositoryA.delete and invoke onDelete(Event)

通过这种方法,您已经意识到 repoA repoB 之间存在松散耦合(强制执行开放/关闭原则 - 在收盘方面),因此 repoA < / strong>现在(再次)

问候。