There are several similar questions on this matter, by I still haven't found enough reasons to decide which way to go.
The real question is, is it reasonable to abstract the NHibernate using a Repository pattern, or not?
It seems that the only reason behind abstracting it is to leave yourself an option to replace NHibernate with a different ORM if needed. But creating repositories and abstracting queries seems like adding yet another layer, and doing much of the plumbing by hand.
One option is to use expose
IQueryable<T> to the business layer and use LINQ, but from my experience LINQ support is still not fully implemented in NHibernate (queries simply don't always work as expected, and I hate spending time on debugging a framework).
Although referencing NHibernate in my business layer hurts my eyes, it is supposed to be an abstraction of data access by itself, right?
What are you opinions on this?
Good quiestions. I was also thinking about them a few days ago.
Actually, try out NHibernate 3.0 alpha (or the current trunk), its new LINQ provider is much greater than the previous ones. (So far I only found one method which is not working, but it is possible to hook in your own mechanism if you run into something it doesn't support by default.) I had no problems (yet?) with using the current trunk. You can find a "nightly" build on the http://www.hornget.net/packages/ site, along with a FluentNHibernate build against it. Fluent really increases your productivity if you know how to use it. The SO community really helped me with that, too.
If you are okay with your business layer having a direct dependency on NHibernate, or you are writing a smaller application which remains maintainable without this kind of abstraction, you're good to go without the repository pattern. However, if you do it right, it can save you a lot of redundant coding.
The reason for abstracting it isn't only useful because then you can replace NHibernate later with another ORM, but it is a good practice because of a concept called Separation of Concerns. Your business logic layer shouldn't care or know anything about how to access the data it works with. This makes maintaining the application or its different layers easier, which also makes teamwork easier: If X creates the data access layer, and Y writes the business logic, they don't have to know each others' work in detail.
IQueryable<T> is a very good idea, and that is exactly what many repository implementations are doing right now. (And me too, although I preferred to write it in a static class.) And of course you'll have to expose some methods to insert or update an entity, or methods for beginning and commiting transactions, if you want to. (The BeginTransaction should just return an
IDisposable to avoid leaking out an NHibernate interface, and that'll be fine.)
I can give you some directions: check out SharpArchitecture's or FubuMVC Contrib's implementations to get some ideas about how do do it right, and this is how I solved it.