1

I am using nhibernate and the nhibernate profile what keeps throwing this alert.

Use of implicit transactions is discouraged"

I actually wrap everything in a transaction through ninject

  public class NhibernateModule : NinjectModule
    {
        public override void Load()
        {
            Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
            Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope()
                                                                                      .OnActivation(StartTransaction)
                                                                                      .OnDeactivation(CommitTransaction);
        }

        public void CommitTransaction(ISession session)
        {

            if (session.Transaction.IsActive)
            {
                session.Transaction.Commit();
            }

        }

        public void StartTransaction(ISession session)
        {
            if (!session.Transaction.IsActive)
            {
                session.BeginTransaction();
            }
        }
    }

So this should wrap everything in a transaction and it seems to work with anything that is not lazy loading.

If it is lazy loading though I get the error. What am I doing wrong.

chobo2
  • 83,322
  • 195
  • 530
  • 832
  • When you say "the error", you mean "implicit transactions is discouraged"? – Merlyn Morgan-Graham Jun 05 '11 at 20:42
  • @Merlyn Morgan-Graham - Yes that is the error I am getting because for some reason it is not wrapping my statements in a transaction when I call it through lazy loading. – chobo2 Jun 05 '11 at 20:47
  • This blog post (comments section) seems to tell me that transactions don't make sense with lazy loading - http://ayende.com/blog/3775/nh-prof-alerts-use-of-implicit-transactions-is-discouraged – Merlyn Morgan-Graham Jun 06 '11 at 00:08
  • @ Merlyn Morgan-Graham - I just got from the one comment in that post about how you should manage your load better. – chobo2 Jun 06 '11 at 01:05

1 Answers1

1

This is, in fact, still an implicit transaction, or relatively close to it. The injector is blissfully ignorant of everything that's happened between activation and deactivation and will happily try to commit all your changes even if the state is incorrect or corrupted.

What I see is that you're essentially trying to cheat and just have Ninject automatically start a transaction at the beginning of every request, and commit the transaction at the end of every request, hoping that it will stop NH from complaining. This is extremely bad design for several reasons:

  1. You are forcing a transaction even if the session is not used at all (i.e. opening spurious connections).
  2. There is no exception handling - if an operation fails or is rolled back, the cleanup code simply ignores that and tries to commit anyway.
  3. This will wreak havoc if you ever try to use a TransactionScope, because the scope will be completed before the NH transaction is.
  4. You lose all control over when the transactions actually happen, and give up your ability to (for example) have multiple transactions within a single request.

The NH Profiler is exactly right. This isn't appropriate use of NH transactions. In fact, if you're lazy loading, the transaction might end up being committed while you're still iterating the results - not a good situation to be in.

If you want a useful abstraction over the transactional logic and don't want to have to twiddle with ISession objects then use the Unit Of Work pattern - that's what it's designed for.

Otherwise, please code your transactions correctly, with a using clause around the operations that actually represent transactions. Yes, it's extra work, but you can't cheat your way out of it so easily.

Aaronaught
  • 120,909
  • 25
  • 266
  • 342
  • How does the Unit of Work pattern work with the repository/service layer pattern? – chobo2 Aug 16 '11 at 15:51
  • @chobo2: They are complementary. The UOW is intended to be domain- and persistence-ignorant. In fact, if you look around the web for information on using the repository pattern with NHibernate you will probably see many of them advocating the UOW at the same time. Technically the `ISession` is supposed to be considered a unit of work, but... kinda not really. A true UOW saves *all* your work when you commit it and discards *all* of it if you don't; the session saves it anyway but is just totally nondeterministic about *when*. – Aaronaught Aug 16 '11 at 21:02
  • Do you have any good tutorials that show all of these. I been looking and still kinda confused how everything will look(what do I need to ninject, how would a simple method in my service layer look like with unit of work, how does the repository work? Does it know anything about the unit of work?) – chobo2 Aug 18 '11 at 18:08
  • @chobo2 is there something wrong with the link that was posted? It has a usage section. Just don't use `Current` when you're doing DI, instead inject the `IUnitOfWork`. – Aaronaught Aug 18 '11 at 20:42
  • I feel I am learning more about TDD than actually the unit of work with all the unit tests and mockups he is making. So I find I am losing focus on what I actually want to learn. – chobo2 Aug 18 '11 at 21:00
  • I been trying around with the unit of work and repo pattern. You can see it here. http://stackoverflow.com/questions/7113245/need-a-simple-example-of-using-nhibernate-unit-of-work-repository-pattern-s not sure if I am on the right track though – chobo2 Sep 09 '11 at 20:35