Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository Pattern with NHibernate?

I am wondering how much should my service layer know of my repository? In past project I always returned lists and had a method for each thing I needed.

So if I needed to return all rows that had an Id of 5 that would be a method. I do have generic repository for create, update, delete and other NHibernate options but for querying I don't.

Now I am starting to use more IQueryable as I started to run into problems of having so many methods for each case.

Say if I needed to return all that had a certain Id and needed 3 tables that where eager loaded this would be a new method. If I needed a certain Id and no eager loading that would be a separate method.

So now I am thinking if I method that does the where clause part and return IQueryable then I can add on the result (i.e. if I need to do eager loading).

At the same time though this now makes the service layer more aware of the repository layer and I no longer can switch out the repository as easy as now I have specific NHibernate in the service layer.

I am also not sure how that would effect mocking.

So now I am wondering if I go down this route if the repository is needed as it now seems like they have been blended together.

Edit

If I get rid of my repository and just have the session in my service layer is there a point to having a unit of work class then?

public class UnitOfWork : IUnitOfWork, IDisposable
    {
        private ITransaction transaction;
        private readonly ISession session;

        public UnitOfWork(ISession session)
        {
            this.session = session;
            session.FlushMode = FlushMode.Auto;
        }

        /// <summary>
        /// Starts a transaction with the database. Uses IsolationLevel.ReadCommitted
        /// </summary>
        public void BeginTransaction()
        {
            transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
        }

        /// <summary>
        /// starts a transaction with the database.
        /// </summary>
        /// <param name="level">IsolationLevel the transaction should run in.</param>
        public void BeginTransaction(IsolationLevel level)
        {
            transaction = session.BeginTransaction(level);
        }

        private bool IsTransactionActive()
        {
            return transaction.IsActive;
        }

        /// <summary>
        /// Commits the transaction and writes to the database.
        /// </summary>
        public void Commit()
        {
            // make sure a transaction was started before we try to commit.
            if (!IsTransactionActive())
            {
                throw new InvalidOperationException("Oops! We don't have an active transaction. Did a rollback occur before this commit was triggered: "
                                                            + transaction.WasRolledBack + " did a commit happen before this commit: " + transaction.WasCommitted);
            }

            transaction.Commit();
        }

        /// <summary>
        /// Rollback any writes to the databases.
        /// </summary>
        public void Rollback()
        {
            if (IsTransactionActive())
            {
                transaction.Rollback();
            }
        }

        public void Dispose() // don't know where to call this to see if it will solve my problem
        {
            if (session.IsOpen)
            {
                session.Close();
            }

        }
like image 485
chobo2 Avatar asked Jan 01 '12 22:01

chobo2


2 Answers

Everyone has an opinion how to use the repository, what to abstract etc. Ayende Rahien has got few good posts about the issue: Architecting in the pit of doom: The evils of the repository abstraction layer and Repository is the new Singleton. Those give you some pretty good reasons why you shouldn't try to create yet another abstraction on top of NHibernate's ISession.

like image 183
Toni Parviainen Avatar answered Nov 16 '22 03:11

Toni Parviainen


The thing about NHibernate is that it gives you the most if you don't try to abstract it out. Making your service layer depend on NHibernate is not necessarily a bad thing. It gives you control over sessions, caching and other NHibernate features, and thus enables you to imporove performance, not to mention saving you from all the redundant wrapping code that you've mentioned.

like image 2
Ilya Kogan Avatar answered Nov 16 '22 04:11

Ilya Kogan