【问题标题】:Why is an interface used when implementing the repository pattern, with entity framework?为什么在使用实体框架实现存储库模式时使用接口?
【发布时间】:2013-10-11 23:49:27
【问题描述】:

在结合实体框架实现存储库模式时,为什么我看到许多示例使用其存储库类的接口?一个具体的参考例子是here

界面的意义何在?为什么不只是课堂?真的需要不止一个类来订阅那个非常具体的接口吗,例如只针对员工?

【问题讨论】:

    标签: c# entity-framework repository-pattern


    【解决方案1】:

    这是一种经常使用的模式,经常专门用于单元测试,而不是真正特定于实体框架或存储库模式,甚至任何数据访问类型。另一个很大的好处是,它使后者有机会在不更改使用它的代码的情况下提供替代实现。 以这段代码为例,它使用dependency injection 模式:

    public class EmployeeService
    {
        private readonly IEmployeeRepository employeeRepository;
    
        public EmployeeService(IEmployeeRepository employeeRepository)
        {
            this.employeeRepository=employeeRepository;
        }
    
        public IEnumerable<Employee> GetAllEmployees()
        {
            IEnumerable<Employee> employeeList=this.employeeRepository.GetAll();
            //Optionally do some processing here
            return employeeList;
        }
    }
    

    通过在存储库中拥有接口,请注意,您现在可以完全使用该接口工作,而无需提及实际的存储库,这就是它的真正价值。它主要有两个好处:

    • 如果你想为这个类编写一个自动化的单元测试,你可以给它一个IEmployeeRepository的假实现,它不会进入真正的数据库,而是返回一个硬编码的列表,这样你就可以测试你的方法现在不用担心数据库。这被称为“模拟”,通常是将接口放在那里的主要原因。还有几个库可以自动执行该过程,所有这些库都依赖于它们生成一个实现接口的假类这一事实。到目前为止,这是放置这样一个界面的最常见原因。
    • 您可能会决定在未来某个时候用其他东西替换实体框架,或者说,想要为不同于关系数据库的东西实现存储库。在这种情况下,您将编写另一个存储库,实现完全相同的接口,但做一些完全不同的事情。鉴于使用它的服务仅依赖于接口,只要遵守相同的合同(当然,实际创建 repo 的代码并将其提供给服务必须更改,但这是另一段历史)。这样,无论在何处读取/保存数据,相同的服务都可以正常工作。

    【讨论】:

    • 一夜之间我的思绪已经足够震撼了。谢谢。
    • 那么,当您需要特定方法时,您会怎么做,例如对于帐户存储库,您可能希望按名称获取帐户?您是在 Where 中使用谓词,还是专门为此添加额外的非接口函数?我觉得允许谓词不太可测试。
    • 在这些情况下,您可以向接口和实现类添加任何必需的方法。将其添加为非接口方法,即使是公共方法,也会抵消接口的好处,因为您将不再能够仅使用接口调用它,从而迫使用户耦合到类而不是接口。出于与您相同的原因,我不喜欢在公共接口中使用谓词,事后测试它们会更加复杂,因此除非我想做一些非常通用的事情,否则我会避免使用这些谓词。但是,在内部实现中使用它们是完全可以的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    相关资源
    最近更新 更多