简体   繁体   中英

NHibernate cascade delete

Let me begin with showing the mapping:

Parent:

<bag name="Communicatiekanalen" table="COMMUNICATIEKANAAL" inverse="true" cascade="delete" lazy="true" >
        <key column="SEK_PROFIEL"/>
        <one-to-many class="Crm.Hibernate.Communicatiekanaal,Crm.Hibernate" />
</bag>

Child:

<many-to-one name="SekProfiel" column="SEK_PROFIEL" class="Crm.Hibernate.Profiel,Crm.Hibernate" />

In other words: a profile can have many communication channels.

On the UI (user-interface [ASP.NET Webforms] ) the following event is fired (deleting a profile with communication channels attached to it) :

    var profielDao = CrmConfiguration.GetDaoFactory().GetProfielDao();
    var profiel = profielDao.GetById(2194, true); //lets say '2194' is an ID that exists
    profielDao.Delete(profiel);

(the DaoFactory is located in one project file and the UI is an ASP.NET Website)

This code works.

IMPORTANT: the code is using the NHibernate 'open-session-in-view' pattern.

I have a service implementation that fires the same code (deleting a profile with communication channels). Some code...

            var daof = CrmConfiguration.GetDaoFactory();
            CrmSettings.Instance.UserID = user;
            var profielDao = daof.GetProfielDao();

            profielDao.BeginTransaction();
            var profiel = profielDao.GetById(CrmEntitiesToHibernate.ParseStringToId(profileId), true);
            profielDao.Delete(profiel);
            profielDao.EndTransaction();

Where 'EndTransaction()' does a 'commit'. I test this code with an 'unit test':

    [TestMethod]
    public void TestDeleteProfile()
    {
        //Getting a valid NEW profile
        var profile = GetSecundaryProfile();
        //Adding a communication channel to the profile
        CrmClient.AddCommunicationChannelForProfile(GetPlainCommunicationChannel(), profile.Id, CurrentUserId);
        //Calling the 'delete profile' method on the service --> FAIL - no cascade
        CrmClient.DeleteProfile(profile.Id, CurrentUserId);
    }

This code fails. The following error is bugging me:

The DELETE statement conflicted with the REFERENCE constraint "R2_PROFIEL". The conflict occurred in database "CRM_ontw", table "dbo.COMMUNICATIEKANAAL", column 'SEK_PROFIEL'. The statement has been terminated.

This means that the cascade didn't happen at all. Executed from the UI it works , but when fired from the ' service implementation ', it fails . Any ideas or suggestions that could help me?

Thanks in advance


Edit: the following generic code delete's an object

    public void Delete(T entity)
    {
        try
        {
            OnDelete(entity);
        }
        catch (Exception)
        {
            SessionManager.Instance.RollbackTransactionOn(SessionFactoryConfigPath);
            throw;
        }
        session.Delete(entity);
    }

Setting the all-delete-orphan doesn't fix the problem.

I've found the problem. The NHibernate 'open-session-in-view' pattern closes the session after commiting the changes to the database (so when the requests ends, the sessions gets closed):

        finally
        {
            // No matter what happens, make sure all the sessions get closed
            foreach (SessionFactoryElement sessionFactorySettings in openSessionInViewSection.SessionFactories)
            {
                SessionManager.Instance.CloseSessionOn(sessionFactorySettings.FactoryConfigPath);
            }
        }

But my EndTransaction() implementation on the service side didn't.

So with a few tweaks I created this EndTransaction() method:

public void EndTransaction()
{
    try
    {
        SessionManager.Instance.CommitTransactionOn(SessionFactoryConfigPath);
    }
    finally
    {
        SessionManager.Instance.CloseSessionOn(SessionFactoryConfigPath);
    }
}

Try setting cascade="delete" to cascade="all-delete-orphan"

Also, ensure that in both instances, the parent is being read and saved by the same ISession instance. As someone commented, we need to see the implementation of your .Delete() method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM