4

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

我正在使用实体框架代码优先方法,并且我有两个模型类

学生
教师

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

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

   TEntity FindOne(Expression<Func<TEntity, bool>> where = null);       
}

所以这个接口可以在两个模型类中使用。如果学生类有更多的方法,我可以在哪里定义这些方法?例如

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

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

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

请指导我,我很困惑。

4

3 回答 3

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...
}

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

public class StudentRepository : GenericRepository<Student>
{
    // here you get all the goodies + you can add your own stuff
}

和:

public class TeacherRepository : GenericRepository<Teacher>
{
    // here you get the same goodies, you don't need to re-implement them
}

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

于 2013-05-27T07:35:07.503 回答
6

通用存储库毫无价值。它们只是做与实体框架相同的事情,并且大多数实现都暴露了IQueryable<T>

那为什么这么糟糕呢?

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

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

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

每次通过IQueryable<T>.

因此,您仍然需要了解 Entity Framework 的工作原理。因此,您可以直接使用 EF 而不是使用通用存储库。

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

于 2013-05-29T06:28:21.503 回答
2

我认为通用存储库的想法试图概括太多,我认为单独的接口更好,因为它们提供了更有意义的合同,这个博客解释得很好,并提供在“幕后”使用通用存储库。

于 2013-05-27T07:31:49.053 回答