По моему мнению (и, по мнению некоторых других людей), хранилище должно быть интерфейсом, который скрывает доступ к данным в интерфейсе, который имитирует интерфейс коллекции.Вот почему репозиторий должен быть 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 работает достаточно хорошо для большинства запросов, которые мне нужно сделать.