3

how can I make it so on every http request I start a transaction and at the end I commit my transactions?

I am already using InRequestScope for my sessions and have this for my ninject.

public class NhibernateSessionFactory
    {
        public ISessionFactory GetSessionFactory()
        {
           ISessionFactory fluentConfiguration = Fluently.Configure()
                                                  .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("ConnectionString")))
                                                  .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Map>().Conventions.Add(ForeignKey.EndsWith("Id")))
                                                  .ExposeConfiguration(cfg => cfg.SetProperty("adonet.batch_size", "20"))
                                                  //.ExposeConfiguration(BuidSchema)
                                                  .BuildSessionFactory();

            return fluentConfiguration;
        }

        private static void BuidSchema(NHibernate.Cfg.Configuration config)
        {
            new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
        }
    }


public class NhibernateSessionFactoryProvider : Provider<ISessionFactory>
    {   
        protected override ISessionFactory CreateInstance(IContext context)
        {
            var sessionFactory = new NhibernateSessionFactory();
            return sessionFactory.GetSessionFactory();
        }
    }

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

Edit

I know have ninject set to OnActivation and OnDeactivation

but what I am finding weird is this.

   -- statement #1
begin transaction with isolation level: Unspecified

-- statement #2
select TOP ( 1 /* @p0 */ ) student0_.StudentId         

-- statement #3
begin transaction with isolation level: Unspecified

-- statement #4
select TOP ( 1 /* @p0 */ ) student0_.StudentId   

-- statement #5
select courseperm0_.PermissionId    

-- statement #6
begin transaction with isolation level: Unspecified

-- statement #7
commit transaction

-- statement #8
SELECT this_.TaskReminderId as TaskRemi1_13_0_

-- statement #9
SELECT this_.ReminderId                as ReminderId0_2_,

-- statement #10
SELECT this_.ReminderId                as ReminderId8_2_,

The above is from the profiler but I stripped away most of the query as I did not think is relivent to the problem.

Look how is all of sudden for statement 8,9,10 it does not make a transaction for. But before that it made 3. I don't understand this.

Edit 2

I found this post

 .OnActivation(session =>
            {
                session.BeginTransaction();
                session.FlushMode = FlushMode.Commit;
            })

It seems this does help a bit with my problem(still have the problem with lazy loading). I am wondering why this works though and if something can go wrong by using this.

Community
  • 1
  • 1
chobo2
  • 83,322
  • 195
  • 530
  • 832

1 Answers1

2

Add activation/deactivaion actions to your session binding:

.OnActivation(session => session.Transaction.Begin())
.OnDeactivation(CommitTransaction)

public void CommitTransaction(ISession session)
{
    try 
    {
        session.Transaction.Commit();
    }
    catch(Exception e)
    {
        // Add some exception handling (rollback, show error to user, ...) 
        throw;
    }
}
Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • @Remo Gloor - Ok I get the first one. On Activation but I don't get the deactivation. You have "CommitTransaction" and then you got some method called BeingTransaction that seems to commit the transaction. See weird as I would have thought that would be the EndTransaction. – chobo2 Jun 04 '11 at 19:23
  • My fault should be CommitTransaction. Copied the code wrongly. – Remo Gloor Jun 05 '11 at 12:04
  • @ Remo Gloor - Should I not be checking for if the transaction is active first? I guess I don't need to close the session as ninject should take care of that. – chobo2 Jun 05 '11 at 20:08
  • @chobo2 If someone closes the transaction at some point you should check. My example only shows where begin and comit should be done. The exact implementation depends on the rest of the application. – Remo Gloor Jun 05 '11 at 20:13
  • @Remo Gloor - What I am finding is everytime I use lazy loading though it does not wrap these around in a transaction everything else gets wrapped into one. – chobo2 Jun 05 '11 at 20:27
  • @chobo2 What do you mean by lazy loading? Dependencies or DTO's? – Remo Gloor Jun 05 '11 at 23:45
  • @Remo Gloor - I mean when you say have a one to many relationship to another table. You do a query to get TableA back and then you go TableA.TableB and you get the stuff from TableB through lazy loading. – chobo2 Jun 06 '11 at 01:04
  • @RemoGloor - What if an exception happens (for instance when writing to db). How can we check an exception has happened and rollback the transaction? – kaptan Oct 23 '14 at 00:55
  • @RemoGloor - In other words, is there any sort of flag under Context that would say an exception has happened, or should I make my own? – kaptan Oct 23 '14 at 01:07
  • @RemoGloor - BTW, By exception I mean any exception during the whole request not just when writing to db at commit time which is catchable as shown in your code above. – kaptan Oct 23 '14 at 01:16
  • @RemoGloor - I posted the question here: http://stackoverflow.com/questions/26519895/how-to-rollback-nhibernate-transaction-when-an-exception-occurs-during-request-h – kaptan Oct 23 '14 at 01:33