通用存储库模式有重复的代码,那么有什么好处呢?

Sho*_*jaz 4 c# repository-pattern entity-framework-4 ef-code-first

我在c#中理解存储库模式.当我研究通用存储库模式时,我很困惑.它有很多重复.我对这种模式有一些疑问.

我使用实体框架代码第一种方法,我有两个模型类

学生
教师

如果我有一个通用接口,我将使用多少通用接口

public interface IRepository<TEntity>
{
   IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null);

   TEntity FindOne(Expression<Func<TEntity, bool>> where = null);       
}
Run Code Online (Sandbox Code Playgroud)

因此,此接口可用于两个模型类.如果Student类有更多的方法可以定义这些方法?例如

public class StudentRepo<TEntity> : IRepository<TEntity> where TEntity : class
{
    public virtual IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null)
    {
        return null != where ? Context.Set<TEntity>().Where(where) : Context.Set<TEntity>();
    }

    public virtual TEntity FindOne(Expression<Func<TEntity, bool>> where = null)
    {
        return FindAll(where).FirstOrDefault();
    }

    public void update()
    {
    }

    public int FindId()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我添加了两个新方法update(),FindId()StudentRepo哪里可以定义这些方法?

如果我想在这里添加这两个方法,IRepository我必须为Teacher类调用这些方法.它会带来什么好处?如果我为两个类创建单独的接口,这是更好的方法吗?像IStudent和ITeacher一样,我可以定义我想要使用的那些方法,并且不会使用不必要的方法.

请指导我,我很困惑.

Dim*_*rov 6

您可以拥有一个实现IRepository,例如:

public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    public virtual IEnumerable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null)
    {
        // implementation ...
    }

    public virtual TEntity FindOne(Expression<Func<TEntity, bool>> where = null)
    {
        // implementation
    }

    public void Update(TEntity entity)
    {
        // update your entity ...
    }

    // etc...
}
Run Code Online (Sandbox Code Playgroud)

然后让自己的存储库继承自它:

public class StudentRepository : GenericRepository<Student>
{
    // here you get all the goodies + you can add your own stuff
}
Run Code Online (Sandbox Code Playgroud)

和:

public class TeacherRepository : GenericRepository<Teacher>
{
    // here you get the same goodies, you don't need to re-implement them
}
Run Code Online (Sandbox Code Playgroud)

这样您就不必重新实现通用存储库中定义的所有方法,但是您可以添加自己更复杂的方法.


jga*_*fin 6

通用存储库毫无价值.它们与实体框架完全相同,并且大多数实现都暴露在外IQueryable<T>.

那么为什么那么糟糕?

存储库模式用于在数据源和代码之间创建抽象.创建该抽象是为了降低复杂性并减少这些层之间的耦合.

通用存储库最初似乎是一个不错的选择,但由于每个实体(根聚合)都有自己独特的功能,因此您始终必须编写自定义查询来获取它们.

为了解决这个问题,最通用的实现暴露IQueryable<T>.这是一件坏事,因为没有100%完整的Linq to Sql提供程序(一组将LINQ语句转换为SQL语句的类).每个提供程序都必须使用自定义命令来支持eager/lazy加载,支持INsql子句等.

每次使用存储库时,您始终必须了解这些自定义项IQueryable<T>.

因此,您仍然需要了解实体框架的工作原理.因此,您可以直接使用EF而不是使用通用存储库.

如果您真的想要使用存储库模式,请首先使用您的所有类设计代码.然后创建数据库.也就是说,在代码之后安装DB,反之亦然.并确保您的存储库是100%完整的抽象(例如谷歌persistance ignorance)