Ответ 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 работает достаточно хорошо для большинства запросов, которые мне нужны.