Question

In my web application, somewhere during request cycle I call following method on repository:

     repository.Delete(objectToDelete);   

and this is NHibernate implementation:

    public void Delete(T entity)
    {
        if (!session.Transaction.IsActive)
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Delete(entity);
                transaction.Commit();
            }
        }
        else
        {
            session.Delete(entity);
        }
    }

And session.Delete(entity) (inside using statement) fails - which is fine cos I have some database constraints and this is what I expected. However, at the end of the request in Global.asax.cs I close the session with following code:

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        ISession session = ManagedWebSessionContext.Unbind(HttpContext.Current, sessionFactory);

        if (session != null)
        {
            if (session.Transaction != null && session.Transaction.IsActive)
            {
                session.Transaction.Rollback();
            }
            else
            {
                session.Flush();
            }
            session.Close();
        }
    }

This is the same session that was used to delete the object. And now, when:

session.Flush();

is called, NHibernate tries to perform the same DELETE operation - that throws exception and application crushes. Not exactly what I wanted, as I have already handled exception before (on repository level) and I show preety UI message box.

How can I prevent NHibernate from trying to perform DELETE (and I guess UPDATE operation in other scenarios) action once again when that session.Flush is called. Basicall I haven't designed that Application_EndRequest so I'm not sure whether it's a good approach to Flush everything.

Thanks

Was it helpful?

Solution

The flush-mode of NHibernate is by default set to 'auto', which means (amongst other things) that committing the transaction will cause NHibernate to flush and the delete fails.

At the end of the request you manually flush the session again, telling NHibernate to do the delete again (since there is no active transaction).

The reason that this is not working as expected, is because your expectations are wrong. A NHibernate session is a unit of work, i.e. everything your application does in one request. Transactions are completely unrelated. The fact that flushing the session fails the first time, is also the reason that it fails the second time.

If you want to prevent NHibernate to perform the delete a second time, you shouldn't flush twice, only once. Either by committing the transaction or by doing it manually.

On a somewhat unrelated note: you are using NHibernate and transactions wrong. It will give you massive problems later on. There are some good resources online about how to use NHibernate in a web application.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top