Как построить общий репозиторий - PullRequest
4 голосов
/ 29 сентября 2010

Я занимаюсь разработкой веб-приложения в ASP.NET MVC с помощью NHibernate.

Исходя из статей и учебных пособий, которые я нашел в Google, я использую репозиторий для своих классов.

У меня 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 ]

6 голосов
/ 29 сентября 2010

Из другой поток :

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);
  }   
}
4 голосов
/ 29 сентября 2010

Вы должны создать общий репозиторий, который вы можете использовать в общем случае, и, если для определенного класса требуются дополнительные методы, добавьте его, используя наследование. Используя ваш пример:

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 */ }
}
3 голосов
/ 29 сентября 2010

Вот мой ответ на аналогичный вопрос (28 голосов на данный момент):

Преимущество создания общего хранилища по сравнению с конкретным хранилищем для каждого объекта?

Идея состоит в том, чтобы обобщать реализацию, а не интерфейс.Вместо внешнего универсального интерфейса репозитория создайте обращенный внутрь базовый класс общего репозитория, который вы используете для простой реализации специфичных для сущности интерфейсов.

Edit: Я должен отметить, чтоуниверсальные репозитории выполняют очень отличную функцию , чем определенные репозитории.Хранилища предназначены для инкапсуляции механизмов доступа к данным за запросами объекта, включая всю логику запроса.Универсальный репозиторий инкапсулирует возможность создания запросов, но не инкапсулирует какой-либо специфический запрос о сущности.

Смысл в том, чтобы не делать потребителей репозитория ответственными за написание собственных запросов.Универсальный репозиторий живет на том же уровне абстракции, что и ORM;конкретный репозиторий живет на уровне выше этого.

2 голосов
/ 29 сентября 2010
2 голосов
/ 29 сентября 2010

Посмотрите на мой ответ на вопрос " Общий метод хранилища Entity Framework MVC 2 Asp.net. Как обновить определенный столбец " - он должен дать вам хорошее представление о том, что делать.

HTH, Чарльз

Например

Базовая модель:

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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...