如何构建通用存储库

时间:2010-09-28 20:00:47

标签: asp.net-mvc nhibernate design-patterns oop repository

我正在使用NHibernate在ASP.NET MVC中开发一个Web应用程序。

根据我在Google上发现的文章和教程,我正在为我的课程使用Repository。

我有10个类和10个存储库。今天我发现除了班级以外,90%的矿藏都是完全相同的。这是一个例子:

public class PromocaoRepository:IPromocaoRepository {
    private ISession Session;

    public PromocaoRepository() {
        this.Session = NHibernateSessionFactory.OpenSession();
    }

    public void Add(Promocao promocao) {
        using(ITransaction transaction = this.Session.BeginTransaction()) {
            this.Session.Save(promocao);
            transaction.Commit();
        }
    }

    public void Edit(Promocao promocao) {
        using(ITransaction transaction = this.Session.BeginTransaction()) {
            this.Session.Update(promocao);
            transaction.Commit();
        }
    }

    public void Remove(Promocao promocao) {
        using(ITransaction transaction = this.Session.BeginTransaction()) {
            this.Session.Delete(promocao);
            transaction.Commit();
        }
    }

    public Promocao GetById(int id) {
        return this.Session.Get<Promocao>(id);
    }

}

有一种方法可以做一种我可以在我所有课程中使用的通用存储库吗?

如果可能的话,如果我需要为特定类创建特定方法,我该怎么办?

5 个答案:

答案 0 :(得分:6)

来自another thread

public interface IRepository<T> : IQueryable<T>
{
  void Add(T entity);
  T Get(Guid id);
  void Remove(T entity);
}

public class Repository<T> : IQueryable<T>
{
  private readonly ISession session;

  public Repository(ISession session)
  {
    session = session;
  }

  public Type ElementType
  {
    get { return session.Query<T>().ElementType; }
  }

  public Expression Expression
  {
    get { return session.Query<T>().Expression; }
  }

  public IQueryProvider Provider
  {
    get { return session.Query<T>().Provider; } 
  }  

  public void Add(T entity)
  {
    session.Save(entity);
  }

  public T Get(Guid id)
  {
    return session.Get<T>(id);
  }

  IEnumerator IEnumerable.GetEnumerator()
  {
    return this.GetEnumerator();
  }

  public IEnumerator<T> GetEnumerator()
  {
    return session.Query<T>().GetEnumerator();
  }

  public void Remove(T entity)
  {
    session.Delete(entity);
  }   
}

答案 1 :(得分:4)

您应该创建一个通用存储库,您可以在一般情况下使用它,如果特定类需要任何额外的方法,请使用继承添加它。使用您的示例:

public class GenericRepository<TEntity> :IGenericRepository<TEntity> {
    private ISession Session;

    public GenericRepository() {
        this.Session = NHibernateSessionFactory.OpenSession();
    }

    public void Add(TEntity instance) {
        using(ITransaction transaction = this.Session.BeginTransaction()) {
            this.Session.Save(instance);
            transaction.Commit();
        }
    }

    /* other methods */ 
}

public class SpecificRepository : GenericRepository<SpecificEntity>, ISpecificRepository 
{
    public void SpecialQuery()  { /* added method implementation */ }
}

答案 2 :(得分:3)

以下是我对类似问题的回答(截至目前为28票):

Advantage of creating a generic repository vs. specific repository for each object?

这个想法是将实现泛化,而不是接口。而不是向外的通用存储库接口,创建一个面向内部的通用存储库基类,您可以使用它来轻松实现特定于实体的接口。

编辑:我应该指出,通用存储库提供的非常不同的功能比特定的存储库。存储库旨在封装实体查询背后的数据访问机制,包括所有查询逻辑。通用存储库封装了创建查询的能力,但它没有封装任何关于实体的特定查询。

关键是不要让存储库消费者负责编写自己的查询。通用存储库与ORM处于相同的抽象级别;特定的存储库位于该级别之上。

答案 3 :(得分:2)

看看我对“Asp.net MVC 2 Entity Framework Generic Repository Method. how to Update a specific Collumn”问题的回答 - 它应该让你知道该怎么做。

HTHS, 查尔斯

E.g。

基础模型:

public interface IDbTable
{
    int Id { get; set; }
    DateTime DateCreated { get; set; }
    DateTime DateUpdated { get; set; }
}

public class DbTable
{
    public int Id { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateUpdated { get; set; }
}

你的模特

public class Category : DbTable
{
    public string Name { get; set; }
}

您的存储库

public interface IBaseRepository<T> where T : class, IDbTable
{
    void Add<T>(T entity);
    void Edit<T>(T entity);
    void Remove<T>(T entity);
    T GetById(int id);
}

public class BaseRepository<T> : IBaseRepository<T>
{
    private ISession Session;

    public BaseRepository()
    {
        this.Session = NHibernateSessionFactory.OpenSession();
    }

    public void Add(T entity)
    {
        entity.DateCreated = DateTime.UtcNow;
        entity.DateUpdated = DateTime.UtcNow;

        using(ITransaction transaction = this.Session.BeginTransaction())
        {
            this.Session.Save(entity);
            transaction.Commit();
        }
    }

    public void Edit(T entity)
    {
        entity.DateUpdated = DateTime.UtcNow;

        using(ITransaction transaction = this.Session.BeginTransaction())
        {
            this.Session.Update(entity);
            transaction.Commit();
        }
    }

    public void Remove(T entity)
    {
        using(ITransaction transaction = this.Session.BeginTransaction())
        {
            this.Session.Delete(entity);
            transaction.Commit();
        }
    }

    public T GetById(int id)
    {
        return this.Session.Get<T>(id);
    }
}

哦,不要忘记具体的实现

public interface ICategoryRepository : IBaseRepository<Category>
{
    Category GetCategoryByName(string categoryName);
}

public CategoryRepository : BaseRepository<Category>
{
    public Category GetCategoryByName(string categoryName)
    {
        //blah
    }
}

答案 4 :(得分:2)