为什么我的 C# 继承不适用于通用存储库模式

Why is my C# Inheritance not working with the Generic Repository Pattern

我定义了一个基本存储库如下:

public abstract class BaseRepository<TEntity> where TEntity : class
{
    protected DbSet<TEntity> dbSet;
    protected readonly DbContext dbContext;

    public BaseRepository()
    {
        this.dbContext = new SchoolDemoEntities();
        dbSet = dbContext.Set<TEntity>();
    }

    public BaseRepository(DbContext dbContext)
    {
        this.dbContext = dbContext;
        dbSet = dbContext.Set<TEntity>();
    }
}

以上是我对所有其他存储库 class 的基础 class。其中之一是阅读...

public class ReadRepository<TEntity>
: BaseRepository<TEntity>
, IReadRepository<TEntity>
  where TEntity : class
{
    #region Constructors

    public ReadRepository() : base() { }

    public ReadRepository(DbContext dbContext)
        : base(dbContext) { }

    #endregion

    /// <summary>
    /// Maps to read functionality in the database. Reads a single record.
    /// </summary>
    /// <param name="id">an integer identifier which maps to the primary key</param>
    /// <returns>TEntity -> a single instance of the class</returns>
    public TEntity Read(int id)
    {
        return dbSet.Find(id);
    }
}

以上只是其中的一部分class,还有其他的读取方法。还有一个 class (删除)继承了这个 read class...

public class DeleteRepository<TEntity>
: ReadRepository<TEntity>
, IDeleteRepository<TEntity>
  where TEntity : class
{
    #region Constructors

    public DeleteRepository() : base() { }

    public DeleteRepository(DbContext dbContext)
        : base(dbContext) { }

    /// <summary>
    /// Maps to delete functionality in the database. Deletes the given record.
    /// </summary>
    /// <param name="entity">A class containing the information to delete.</param>
    /// <returns>int: The number of records affected.</returns>

    #endregion


    public int Delete(TEntity entity)
    {
        dbSet.Remove(entity);
        return dbContext.SaveChanges();
    }
}

我的问题是,据我了解继承,当我在我的控制器中声明和实例删除 class 时,我应该可以访问读取方法,如下所示:

public class CourseController : Controller
{
    IDeleteRepository<Course> deleteRepository = new DeleteRepository<Course>(new DbContext("SchoolDemoEntities"));

    // POST: Course/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public ActionResult DeleteConfirmed(int id)
    {
        //*** The line directly below doesn't work ***
        Course course = deleteRepository.Read(id);


        deleteRepository.Delete(course);
        return RedirectToAction("Index");
    }
}

突出显示的行不起作用。我看不出有什么问题。 C# 只是强调读取方法说:

IDeleteRepository does not contain a definition for 'Read' and no extension method 'Read' accepting a first argument of type 'IDeleteRepository' could be found (are you missing a using directive or an assembly reference?)

我确实定义了接口,而且消息是正确的,它没有被读取。但我不明白为什么我需要一个,因为 Read 存储库实现了它自己的读取方法,而这个具体实现是由 delete 继承的。为什么我需要定义一个已经在我的读取接口中定义并且class并被继承的读取方法。

导致我出现此错误的原因是我试图通过与同一实体的多个连接来解决这个问题。

如果我在我的控制器中明确定义读取 class 如下:

    IReadRepository<Course> readRepository = new ReadRepository<Course>(new DbContext("SchoolDemoEntities"));

然后将突出显示的行更改为...

        Course course = readRepository.Read(id);

然后我得到错误...

The object cannot be deleted because it was not found in the ObjectStateManager.

这确实有道理,因此也是继承的原因。我需要在与删除相同的连接中阅读。使用上述方法执行此操作会关闭读取连接并重新打开它以进行删除。我认为继承应该解决这个问题?但是继承的时候无法访问read方法,不明白为什么。

DeleteRepository 包含 Read 方法,因为它继承自 ReadRepository.

问题是您的局部变量是 IDeleteRepository<Course> 类型 - 这不是 IDeleteRepository<Course>.

上的 Read 方法

如果您将声明更改为正确的类型,您将可以访问这两种方法:

DeleteRepository<Course> deleteRepository = new DeleteRepository<Course>(new DbContext("SchoolDemoEntities"));

如果 Read()IReadRepository 上,让 IDeleteRepository 继承自 IReadRepository 以使您的接口层次结构与您的实现层次结构相匹配,那么这些方法将在你期望的水平。

虽然,正如@Charles Mager 在 中所说,Read()Delete() 应该在基本存储库上,因为存储库模式应该为每个业务对象都有一个存储库,而不是比存储库操作。