NHibernate Insertion Behavior

I would like to get an opinion on the behavior I found when I use the INSERT command with a stateless session in NHibernate (NB. I am using NHibernate 2.1.2)

The fact is that

//STATEFULL SESSION
var session = sessionFactory.OpenSession()
using(var transaction = session.BeginTransaction()){
   var entity = new MyEntityType();
   entity.Id = 1;

   session.Save(entity);

   var entity2 = session.Get<MyEntityType>(1);  
   //OK! It returns saved entity...as I expect

   transaction.Commit();
}

      

but ... in a stateless session, behavior changes ...

//STATELESS SESSION
var session = sessionFactory.OpenStatelessSession()
using(var transaction = session.BeginTransaction()){
   var entity = new MyEntityType();
   entity.Id = 1;

   session.Insert(entity);

   var entity2 = session.Get<MyEntityType>(1);  
   //entity2 IS NULL!!! Why?

   transaction.Commit();
}

      

My question is, how can I check if I have inserted an item in the transaction scope of the session without saving?

+3


source to share


1 answer


Well, stateless ... stateless. So the session cache doesn't give you the inserted object back from memory.

Now why isn't it readable in the database? Because it's not there yet!

Most likely you enabled batching ( adonet.batch_size

xml config parameter or code config property Environment.BatchSize

or didn't disable it via IStatelessSession.SetBatchSize(int)

while it is enabled at the factory session level). If batching is enabled, if your NHibernate database driver supports it, the DML operations are merged as much as possible, down to the configured batch size, and then flushed from the database.

Thus, such a flush with a stateless session can occur:



  • If the "number of batches" has been reached to perform operations.
  • If the transaction is complete.
  • When another DML request is made that differs in more than just its parameter values.
    (In your case, for example, inserting another type of object after inserting, or updating or deleting any type of object after inserting.)
  • Explicitly flushing the dispenser by pressing the internal session interface.
    s.GetSessionImplementation().Flush();

If you want yours Insert

to be sent to the database immediately, turn off batch processing. Setting it on 0

will disable it.

But why are you using stateless session in the first place? Probably in order to insert many objects into an action. In this case, disabling batch processing will depend on your goals.

So you can instead use the internal session interface exposed by the session method GetSessionImplementation()

and explicitly Flush

. But the good thing is that calling internals directly can lead to undefined behavior, so this is not recommended.

+2


source







All Articles