Использование шаблона Generic Repository с плавным nHibernate

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

Я рассматриваю возможность использования чего-то подобного: http://mikehadlow.blogspot.com/2008/03/using-irepository-pattern-with-linq-to.html

Однако я хочу использовать свободное nHibernate вместо Linq-to-SQL (и, конечно, nHibernate.Linq)

Является ли это жизнеспособным?

Как мне настроить эту настройку? Где будут отображаться мои определения сопоставления и т.д.??

В конечном итоге это приложение будет иметь множество аспектов - из WebUI, библиотеки WCF и приложений/служб Windows.

Также, например, в таблице "product", я бы создал класс "ProductManager", который имеет такие методы, как:

GetProduct, GetAllProducts и т.д.

Любые указатели получаются.

Ответы

Ответ 1

По моему мнению (и в некоторых других мнениях людей), репозиторий должен быть интерфейсом, который скрывает доступ к данным в интерфейсе, который имитирует интерфейс коллекции. Поэтому репозиторий должен быть IQueryable и IEnumerable.

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);
  }   
}

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

public interface IUnitOfWork : IDisposable
{
  void Commit();
  void RollBack();
}

Я использую сессию определенной единицы работы NHibernate как сеанс для репозиториев:

public interface INHiberanteUnitOfWork : IUnitOfWork
{
  ISession Session { get; } 
}

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

Ответ 2

Вот мои мысли об общих хранилищах:

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

Я успешно использовал этот шаблон с NHibernate и не обнаружил никаких реальных недостатков.

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

Надеюсь, что это поможет.