jmcd
jmcd

Reputation: 4300

How do I make NHibernate delete child references when I delete a parent?

I have a NewsFeed object mapped as such:

<class name="NewsFeed">
    <id name="NewsFeedId">
        <generator class="guid"/>
    </id>

    <property name="FeedName" not-null="true" />
    <property name="FeedURL" not-null="true" />
    <property name="FeedIsPublished" not-null="true" />
</class>

And Users who can have a Set of Selected feeds that they might be intereseted in, mapped like so:

<class name="SystemUser">
    <id name="SystemUserId">
        <generator class="guid"/>
    </id>


    <set name="SelectedNewsFeeds" table="SystemUserSelectedNewsFeeds" cascade="all">
        <key column="SystemUserId" />
        <many-to-many column="NewsFeedId" class="NewsFeeds.NewsFeed, Domain"/>
    </set>

</class>

What I want to happen is when I delete the parent NewsFeed then all of the SelectedNewsFeed references get deleted too, without having to load each SystemUser and delete the NewsFeed by hand.

What is the best way to achieve this?

UPDATE: Using cascade="all-delete-orphan" instead of "all" still results in an exception when deleting the NewsFeed:

The DELETE statement conflicted with the REFERENCE constraint "FKC8B9DF81601F04F4". The conflict occurred in database "System", table "dbo.SystemUserSelectedNewsFeeds", column 'NewsFeedId'.

Upvotes: 5

Views: 6348

Answers (3)

Trent
Trent

Reputation: 560

JMCD

Your second approach:

Another alternative is to break the many-to-many relationship with a join class in the middle which nHiberate would be able to determine parent-child relationships and the cascade should work.

is actually what the nHibernate folks recommend in their documentation.

Don't use exotic association mappings.

Good usecases for a real many-to-many associations are rare. Most of the time you need additional information stored in the "link table". In this case, it is much better to use two one-to-many associations to an intermediate link class. In fact, we think that most associations are one-to-many and many-to-one, you should be careful when using any other association style and ask yourself if it is really neccessary.

Using two one-to-many associations adds the flexibility to easily add other attributes to the "subscription", such as notification preferences for that particular subscription.

Upvotes: 2

jmcd
jmcd

Reputation: 4300

Since the relation inside the set is many-to-many, nHibernate is not able to tell which end of the relationship is the child and which is the parent, and the quickest way for me to achieve what I wanted was just to write some SQL that I sent through my repository that deleted the respective news feeds from the collection, and then deleted the parent news feed. The next time the collection was hydrated the changes were reflected.

Another alternative is to break the many-to-many relationship with a join class in the middle which nHiberate would be able to determine parent-child relationships and the cascade should work.

Upvotes: 1

Matt Briggs
Matt Briggs

Reputation: 42168

change

cascade="all"

to

cascade="all-delete-orphan"

Reference

Upvotes: 0

Related Questions