每个数据库实体或模块的C#存储库模式

时间:2018-10-10 14:09:39

标签: c# repository-pattern dapper

我有一个c# WebApi项目,该项目使用DapperRepository Pattern作为数据层。

在其他项目中,我按业务逻辑模块创建了存储库。因此,与其创建每个实体的存储库,不如创建一个可以在内部引用多个实体的存储库,因为并非所有实体或数据库表都具有更新,删除和插入。

例如,我曾经有EmployeeRepository,并且在该存储库中,我将处理与员工相关的任何事情,因此在该存储库中,我可以处理许多与员工相关的表。

我的SQL数据库大约有350个表,但是在这个项目中,我只是怀疑如果正确的方法是为每个表或实体都有一个存储库,每个表或实体都有自己的Add,Get,删除,更新,删除等

EmployeeRepository示例中考虑以上内容,如果我要处理的员工数据管理工作可以说5张表:

  • 员工
  • EmployeeContract
  • EmployeeSchedule
  • EmployeeHoliday
  • EmployeeLeave

然后我将有5个存储库,这样:

  • EmployeeRespository
  • EmployeeContractRepository
  • EmployeeScheduleRepository
  • EmployeeHolidayRepository
  • EmployeeLeaveRepository

如果上面的方法是正确的方法,那么是否有任何插件可以为您生成Entity模型类,所以您不必一个个地手工制作?

  

什么是最佳实践模式?

2 个答案:

答案 0 :(得分:2)

我认为没有最佳实践。它更受项目的实际需求以及如何使用这些存储库的驱动。

如果您有350个表,我个人会尝试将它们分组到更大的逻辑存储库中。表结构可能会发生变化,但背后的逻辑仍然存在:您想管理员工人数,而将员工人数数据存储在1个,2个或10个表中则无关紧要。仅出于争论的目的,想象一下您必须移至对象数据库,而所有employyee数据现在都只是一个文档。如果您想保持业务层不变,那么您所有的“表”存储库都必须访问一个文档。

对我来说,指导原则是“什么是我的主要实体,什么是我的从属实体”。如果没有员工,假期或休假是不存在的,所以我可以想象一个Empolyee存储库,上面写着:

GetEmployee(employeeId)
GetEmployeeHoliday(employeeId)
GetEmployeeLeave(employeeId)

从属实体的ID在这里并不重要,因此单独的存储库可能会过大。

如果您决定使用350个存储库,那么我至少会考虑将为您提供通用GetById,Save,Find等方法的通用存储库基类。仅扩展具有更多逻辑的存储库。我认为不超过50,而从第一种方法开始,它们或多或少就是您的“主要实体”。

无论如何,恕我直言,最终取决于您,您的个人喜好和项目需求。

答案 1 :(得分:0)

对我来说,更重要的是,业务层不应该直接与实体合作。取而代之的是,BL使用域或某种DTO,然后将其传递到处理该类型的存储库,该存储库显示“嘿,为我保存”。然后,存储库本身接受BL知道的该域/ dto项,然后将其转换为要用于持久化它的任何实体/技术(EF / Dapper)。将来,如果您需要将其发送给WebApi呼叫,则可以在此处进行更改,而无需担心。但是显然,由于它对业务类型实体做出了反应,所以最终您几乎得到了业务存储库,但我认为它提供了最大的灵活性。

编辑:示例:

public class EmployeeBL
{
    private readonly ICreateEmployeeRepository _repo...

    public IResult CreateEmployee(CreateEmployeeRequestDto dto)
    {
         // Business Logic here
         EmployeeCreateDomainState request = ... Mapped from dto/business logic
         var rowsAffected = _repo.Execute(item);
         ...
    }
}

public class CreateEmployeeRepository : ICreateEmployeeRepository
{
    public CreateEmployeeRepository (IoC inect stuff)...

    public int Execite(EmployeeCreateDomainState request)
    {
        using (var empCtx = EmpDbContextFactory.Create())
        {
             var employeeEntity = ... // Map from request
             var employeeAddressEntity = ... // Map from request
             empCtx.Employees.Add(employeeEntity);                 
             empCtx.EmployeeAddresses.Add(employeeAddressEntity );
             return empCtx.SaveChanges();
        }
    }
}

当然,也许您需要访问多个数据库或其他任何东西,并且可以在此处内部完成所有操作。

您还可以拥有一个通用存储库,例如:

IRepository 和/或IRepository 定义了Execute(或ExecuteAsync),所有回购都与请求一起以1:1的比例使用。更多类,但是您可以在界面周围添加装饰器,以一次向所有存储库添加跨领域关注点。