Catalin DICU
Catalin DICU

Reputation: 4638

NHibernate : Save, Delete then Save the same entity throws StaleStateException

Here is my the test case :

[Test, Explicit]
public void SaveDeleteSaveThrowsTest()
{
    Produit produit = new Produit { Libelle = "Test" };

    using (ISession session = this.SessionProvider.OpenSession())
    {
        session.FlushMode = FlushMode.Auto;

        using (ITransaction transaction = session.BeginTransaction())
        {                    
            session.SaveOrUpdate(produit);
            transaction.Commit();
        }

        using (ITransaction transaction = session.BeginTransaction())
        {
            session.Delete(produit);
            transaction.Commit();
        }

        using (ITransaction transaction = session.BeginTransaction())
        {
            session.SaveOrUpdate(produit);
            Assert.Throws(typeof(StaleStateException), transaction.Commit);
        }
    }
}

The Ids are generated by HiLo.

If I assign 0 to the Id of the entity before saving it the 2nd time it works in this simple case but doesn't work in more complex scenarios where I have a one to many relation (I get the exception "collection owner not associated with session" when trying to delete the parent entity).

Is there a way to make it work ? (save, delete the save again the same entity)

Upvotes: 1

Views: 2523

Answers (3)

Stefan Steinegger
Stefan Steinegger

Reputation: 64628

Try Merge instead of SaveOrUpdate. It looks up the record in the database (additional select before insert or update). Note that Merge has a return value which returns the persistent instance while the given instance is still transient. You may need to clean the session or create a new session to make it work.

Upvotes: 1

Petr Kozelek
Petr Kozelek

Reputation: 1126

Don't you use lazy loading in many-to-* relationship? The problem is you are at first loading the entity, the close session and try to manipulate with (already detached) entity. In such a case sub-entities are proxies attached to closed session. You have to tell NHibernate to re-initialize the proxies: for each sub-entity call NHibernateUtil.Initialize.

Upvotes: 2

Jamie Ide
Jamie Ide

Reputation: 49251

Try calling Session.Save or Session.Lock on the deleted produit object.

However, you should reconsider your design to avoid this problem in the first place. I would keep track of ids to be deleted in a separate collection then perform the deletes when the transaction is committed.

Upvotes: 0

Related Questions