Pelle
Pelle

Reputation: 2785

NHibernates ISession.Clear() not doing it's job?

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

Answers (2)

dotjoe
dotjoe

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

Diego Mijelshon
Diego Mijelshon

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

Related Questions