2

I am working on a system using nhibernate, and I see a lot of the following two lines in exception catch blocks:

session.Flush();
session.RollbackTransaction();

I am very confused by this logic, and it looks like unnecessary work to flush changes, then use transaction rollback practices.

I wanted to setup an argument for removing these flush calls and relying on just the RollbackTransaction method, but I came across this question. Next I read more into the documentation linked, and read the following nugget of information:

If you rollback the transaction you should immediately close and discard the current session to ensure that NHibernate's internal state is consistent.

What does this mean? we currently pair our Session life time with our web request's begin and end operations, so I am worried that the reason we are calling flush THEN rollback is to keep the session in a valid state.

Any ideas?

Community
  • 1
  • 1
Nathan Tregillus
  • 6,006
  • 3
  • 52
  • 91
  • 1
    One thing is clear: calling flush before rollback is redundant. The fact that it is used anywhere in the code, does not change that fact. And also, as stated in doc - rollback should be followed by immediate session end. That's why we should in web have special requests for write and read. If some part of a write operation/request/unit of work failes - rollback, return error message, vanish session.. – Radim Köhler Sep 18 '14 at 05:46

2 Answers2

3

NHibernate does object tracking via the session, and all the changes you do the entities are stored there, when you do the flush those changes are written to the db. If you get an exception while doing so the session state is not consistent with the database state, so if you do a rollback at this stage it will rollback db transaction but session values will not be rolled back.

As per design once that happens the session should not be used further in reliable manner (even Session.Clear() will not help)

If you use the session per request and if you get an error the best approach is to display an error to the user and ask to retry the operation. Other option is to create a brand new session and use it for data fetching purposes to display errors.

Low Flying Pelican
  • 5,974
  • 1
  • 32
  • 43
0

This Flush before Rollback is very likely a trick for working around a bug of the application caused by re-using the session after the rollback.

As you have found by yourself, the session must not be used after a rollback. The application is doing that mistake as per your comment.

Without the Flush before the Rollback, the session still consider the changes as pending, and will commit them at next Flush, defeating the Rollback purpose. Doing that Flush before the rollback causes pending changes to be flushed, then rollback-ed, helping avoiding the session to flush them later.

But the session is still not in a consistent state, so by continuing to use it, the application stays at risk. The session cache still holds the changes that were attempted then rollback-ed. The session does just no more consider them as pending changes awaiting a flush. If the application later usages of the session access those entities, their state will still be the modified one from the rollback-ed transaction, although they will not be considered dirty.

Frédéric
  • 9,364
  • 3
  • 62
  • 112