Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Generic Repository pattern with fluent nHibernate

I'm currently developing a medium sized application, which will access 2 or more SQL databases, on different sites etc...

I am considering using something similar to this: http://mikehadlow.blogspot.com/2008/03/using-irepository-pattern-with-linq-to.html

However, I want to use fluent nHibernate, in place of Linq-to-SQL (and of course nHibernate.Linq)

Is this viable?

How would I go about configuring this? Where would my mapping definitions go etc...?

This application will eventually have many facets - from a WebUI, WCF Library and Windows applications / services.

Also, for example on a "product" table, would I create a "ProductManager" class, that has methods like:

GetProduct, GetAllProducts etc...

Any pointers are greatly received.

like image 870
Alex Avatar asked Apr 06 '10 20:04

Alex


1 Answers

In my opinion (and in some other peoples opinion as well), a repository should be an interface that hides data access in an interface that mimics a collection interface. That's why a repository should be an IQueryable and 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);
  }   
}

I do not implement a SubmitChanges like method in the repository itself, because I want to submit the changes of several repositories used by one action of the user at once. I hide the transaction management in a unit of work interface:

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

I use the session of an NHibernate specific unit of work implementation as session for the repositories:

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

In a real application, I use a more complicated repository interface with methods for things like pagination, eager loading, specification pattern, access to the other ways of querying used by NHiberante instead of just linq. The linq implementation in the NHibernate trunk works good enough for most of the queries I need to do.

like image 196
Paco Avatar answered Sep 21 '22 07:09

Paco