Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

NHibernate 3.0: Working with the Data Access Layer

Save for later
  • 3 min read
  • 15 Oct 2010

article-image

Transaction Auto-wrapping for the data access layer


This article by Jason Dentler, author of NHibernate 3.0 Cookbook, shows how we can set up the data access layer to wrap all data access in NHibernate transactions automatically.

Getting ready


Complete the Eg.Core model and mappings. Download code (ch:1)

How to do it...

  1. Create a new class library named Eg.Core.Data.
  2. Add a reference to NHibernate.dll and the Eg.Core project.
  3. Add the following two DAO classes:

    public class DataAccessObject<T, TId>
    where T : Entity<TId>
    {


    private readonly ISessionFactory _sessionFactory;

    private ISession session
    {
    get
    {
    return _sessionFactory.GetCurrentSession();
    }
    }
    public DataAccessObject(ISessionFactory sessionFactory)
    {
    _sessionFactory = sessionFactory;
    }

    public T Get(TId id)
    {
    return Transact(() => session.Get<T>(id));
    }

    public T Load(TId id)
    {
    return Transact(() => session.Load<T>(id));
    }

    public void Save(T entity)
    {
    Transact(() => session.SaveOrUpdate(entity));
    }

    public void Delete(T entity)
    {
    Transact(() => session.Delete(entity));
    }

    private TResult Transact<TResult>(Func<TResult> func)
    {
    if (!session.Transaction.IsActive)
    {
    // Wrap in transaction
    TResult result;
    using (var tx = session.BeginTransaction())
    {
    result = func.Invoke();
    tx.Commit();
    }
    return result;
    }
    // Don't wrap;
    return func.Invoke();
    }

    private void Transact(Action action)
    {
    Transact<bool>(() =>
    {
    action.Invoke();
    return false;
    });
    }
    }
    public class DataAccessObject<T>
    : DataAccessObject<T, Guid>
    where T : Entity
    {
    }

    
    

  4. Unlock access to the largest independent learning library in Tech for FREE!
    Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
    Renews at $15.99/month. Cancel anytime

How it works...


NHibernate requires that all data access occurs inside an NHibernate transaction and this can be easily accomplished with AOP.

Remember, the ambient transaction created by TransactionScope is not a substitute for an NHibernate transaction.


This recipe shows a more explicit approach. To ensure that at least all our data access layer calls are wrapped in transactions, we create a private Transact function that accepts a delegate, consisting of some data access methods, such as session.Save or session.Get. This Transact function first checks if the session has an active transaction. If it does, Transact simply invokes the delegate. If it doesn't, it creates an explicit NHibernate transaction, then invokes the delegate, and finally commits the transaction. If the data access method throws an exception, the transaction will be rolled back automatically as the exception bubbles up through the using block.

There's more...


This transactional auto-wrapping can also be set up using SessionWrapper from the unofficial NHibernate AddIns project at http://code.google.com/p/unhaddins. This class wraps a standard NHibernate session. By default, it will throw an exception when the session is used without an NHibernate transaction. However, it can be configured to check for and create a transaction automatically, much in the same way I've shown you here.

See also

  • Setting up an NHibernate repository