views:

370

answers:

3

One of practices advocated by Nhibernate experts is to do all actions in inside a transaction.

In a typical 3 tier web architecture, Nhibernate depedency is limited the data layer.

In such a case is it fine to use

  using (var tr = NHibernateSession.Current.BeginTransaction()) {

at the controller level. Won’t this bring in a dependency on Nhibernate to the service layer?

+5  A: 

One way around this is the wrap the NHibernate session and transaction semantics in your own abstrated Interface / implementation class. This way if you ever wanted to say, switch to Linq2Sql, you could create a L2S implementation. However, this still means that transaction semantics will still be in the service layer, but not NHibernate specific calls. Google IRepository<T> for many examples of how to do this.

However, if you don't plan on switching out your ORM in the future, one could argue that having NHibernate in the service layer isn't necessarily a bad thing since NHibernate in itself is the abstraction over the data layer.

Daniel Auger
+1 If you find yourself needing to switch ORMs in the middle of a project, you have bigger problems than this.
Gabe Moothart
+1 we actually did switch ORMs (iBatis -> NHibernate) and it was obvious very very early we needed to make the switch.
ShaneC
fact is i m in the process of moving from subsonic to nhibernate. this is though not common, isn't rare either. by putting all NH dependencies in the data layer, things look neat from a tier architecture.
Quintin Par
I think it comes down to if you want to make the following tradeoff: You can abstract your ORM via the Repository pattern to gain ORM ignorance in your service layer, but the trade off is that you will lose some of your ORM's best features since features very greatly from ORM to ORM. With NHibernate, you are going to be giving up future queries, multi queries, batch inserts etc... There is no clear right or wrong here, but rather a choice to be made to meet your end goal.
Daniel Auger
+3  A: 

Hi Quintin

I'm also looking to do this but haven't settled on an approach yet for lack of time and some YAGNI.

Here is some code I haven't yet tested, but adapted from the open source SharpArch project. I like the interface alot, but I may have changed the NHib implementation a bit, as there are some things I don't love about SharpArch's repository implementation, but you can judge for yourself.

Of course using NHib session.BeginTransaction() introdues NHib dependencies, and not abstracting this out seems at odds with abstracting out IRepository and everything else. I for one would be very interested in what you conclude as a useful abstraction of transactions.

HTH,
Berryl

public interface IDbContext {
    void CommitChanges();
    IDisposable BeginTransaction();
    void CommitTransaction();
    void RollbackTransaction();
}

public class DbContext : IDbContext {
    private readonly ISession _session;

    public DbContext(ISession session)
    {
        Check.RequireNotNull<ISession>(session);
        _session = session;
    }

    public void CommitChanges() { _session.Flush(); }

    public IDisposable BeginTransaction() { return _session.BeginTransaction(); }

    public void CommitTransaction() { _session.Transaction.Commit(); }

    public void RollbackTransaction() { _session.Transaction.Rollback(); }

}
Berryl
have u given any thought about implementing idbcontext from idisposable
Quintin Par
+1  A: 

Calls to some static singleton strewn about like that doesn't seem like a good idea to me. Perhaps it would be better to add a dependency on your own "ITransactionFactory" and leave the NHibernate specific code inside the TransactionFactory implementation.

For SharpArchitecture specifically, there is the TransactionAttribute action filter that is designed to wrap your action methods inside transactions.

Concerning assembly references to NHibernate, that's not something I would personally worry about.

rmacfie
unfortutanely the TransactionAttribute is an actionfilter attribute for web.mvc. will need to change it to work with webforms
Quintin Par