Reputation: 2785
I have a problem with Session.Clear(), as I understand it this statement should completely reset all changes made in the UOW, the cache etc. The problem is that is does not. My scenario is illustrated in the test below. I add to items, there is a dependency between them I then try to delete the item which the other item is dependent upon. This will cause an exception which is correct. I then clear the session. Finally I try add a new item to the database, when flushing NHibernate will once again try to execute the failing delete statement. Am I misunderstanding the use of Session.Clear()? Or am I missing something else here?
[Fact]
public void Verify_Cant_Clear_Delete()
{
var session = SessionFactory.OpenSession();
var category = new ManufacturerCategory { Name = "category" };
var man = new Manufacturer { Category = category, Name = "man" };
session.Save(category);
session.Save(man);
session.Flush();
try
{
// this will cause
// NHibernate.Exceptions.GenericADOException: could not execute batch command.[SQL: SQL not available]
// ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "ManufacturerCategoryId".
// The conflict occurred in database "LabelMaker-Tests", table "dbo.Manufacturers", column 'Category_id'.
session.Delete(category);
session.Flush();
}
catch (Exception ex)
{
// This should clear the session
session.Clear();
}
try
{
var category2 = new ManufacturerCategory { Name = "category 2" };
session.Save(category2);
session.Flush();
}
catch(Exception ex)
{
// this will cause ONCE AGAIN cause
// NHibernate.Exceptions.GenericADOException: could not execute batch command.[SQL: SQL not available]
// ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "ManufacturerCategoryId".
// The conflict occurred in database "LabelMaker-Tests", table "dbo.Manufacturers", column 'Category_id'.
Assert.True(false);
}
}
Upvotes: 2
Views: 917
Reputation: 26940
You should be using transactions and rollback the transaction on an hibernate exception because...
Certain methods of ISession will not leave the session in a consistent state.
http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-exceptions
or let the transaction be implicitly rolled back via dispose()...
using (ISession sess = factory.OpenSession())
using (ITransaction tx = sess.BeginTransaction())
{
// do some work
...
tx.Commit();
}
I'd guess that the Delete() method is one of the inconsistent state methods hinted at in the above quote...
Upvotes: 2
Reputation: 52725
Your assumptions about ISession.Clear()
are not correct.
In particular, as soon as an exception happens, you must discard the session. Clear()
will not fix the state (check out 9.8 Exception Handling)
Also, as dotjoe mentioned, you should be using a transaction to do your work.
Upvotes: 1