views:

393

answers:

5

I'm using Fluent NHibernate in an Asp.net MVC application. I have it set up to start a session and transaction on every request, and commit the transaction at the request end. However, what I want to do is save an object (in this case, a new "Company") and then redirect to that new Company's detail page. How do I get the Id of the new company so that I can redirect? If I get the Id after session.Save(company), it is null. This makes sense as it hasn't yet been committed, however, it still seems there should be a relatively easy way to do this without committing the current transaction and starting a new one.

A: 

Maybe it is not set as autogenerated in database? As Mattias Jakobsson sayed, id should be setted after Session.Save

Сергій
A: 

Since it's a transaction NHibernate postpone changes and thus INSERT is not sent to database - and no ID is generated by the database. Do Session.Flush() - this won't stop transaction but your changes (INSERT) will be executed. Or use assigned IDs. Or don't always start transactions - do this explicitely (as for example S#arp Architecture does with [Transaction] attribute).

queen3
A: 

I think it's a bad idea to start a transaction for every session. I'm using session-per-request and I start and commit a transaction in Session_EndRequest. However, I generally have a transaction on the page so that I can handle any errors that occur there -- by the time EndRequest occurs it's too late to do anything but present a generic error message.

If you're using database generated (identity) IDs then you'll have to flush the session in order to generate the ID.

Jamie Ide
You should use a transaction for every session, even reads. Otherwise you won't be fully utilising the cache - see : http://ayende.com/Blog/archive/2008/12/28/nh-prof-alerts-use-of-implicit-transactions-is-discouraged.aspx
UpTheCreek
I agree, unless you mean one transaction per session. My answer could have been clearer, but I was arguing against allowing the transaction lifetime to equal the request lifetime. It's no problem to have multiple transactions per session.
Jamie Ide
+1  A: 

OK, the problem was elsewhere in my code. You can get the Id immediately after save, even if you haven't committed the transaction or flushed it.

Thanks everyone for the answers, but unfortunately none of them are entirely correct.

Matthew Talbert
+1  A: 

NHibernate generates an id when session.Save() or session.SaveOrUpdate() is called with an transient entity. At this time, the id property of the entity is set and can be used.

If the id generator requires database access, it will happen at this time. So for the Identity generator, the insert will be performed at this time as will any pending inserts.

Otherwise, the insert is pending until the session is flushed which will happen:

  • from some invocations of Find() or Enumerable()
  • from NHibernate.ITransaction.Commit()
  • from ISession.Flush()
Lachlan Roche