cascade delete to collection of joined-subclassess

190 views
Skip to first unread message

pab

unread,
Aug 6, 2014, 12:54:58 PM8/6/14
to fluent-n...@googlegroups.com

Hi. I posted this same topic on stack overflow but there's no been response as yet and unlikely to be one with the view count so I thought I might try asking here. I have a model with a parent class that holds a collection of subclassed children (using TablePerSubClass inheritance). When attempting to to test cascading deletes by calling delete only on the parent object I get a constraint error between the child table and its joined-subclass table. To demonstrate...

    public class ParentMap : ClassMap<Parent> {
        public ParentMap() {
            Id(x => x.Id);
            HasMany(x => x.Children)
                .Cascade.AllDeleteOrphan()
                .ForeignKeyCascadeOnDelete()
                .Inverse();
        }
    }

    public class ChildMap : ClassMap<Child> {
        public ChildMap() {
            Id(x => x.Id);
            References(x => x.Parent).Not.Nullable();
        }
    }

    public class ExtendedChildMap : SubclassMap<ExtendedChild> {
        public ExtendedChildMap() {
            Map(x => x.extraFeature);
        }
    }


To test, I'm using NUnit with my testfixture beginning a new transaction for each test setup, and rolling back the transaction for each teardown. With the following test...


using (var session = sessionFactory.OpenSession()) { using (var transaction = session.BeginTransaction()) { var p = new Parent(); var c1 = new Child() { Parent = p }; var c2 = new ExtendedChild() { Parent = p }; session.SaveOrUpdate(p); session.SaveOrUpdate(c1); session.SaveOrUpdate(c2); Assert.IsTrue(session.Query<Parent>().Count() == 1); Assert.IsTrue(session.Query<Child>().Count() == 2); Assert.IsTrue(session.Query<ExtendedChild>().Count() == 1); session.Delete(p); Assert.IsTrue(session.Query<Parent>().Count() == 0); } }
 

The test fails on the final assertion with

The DELETE statement conflicted with the REFERENCE constraint "FKDB46742824B330ED". The conflict occurred in database "testDB", table "dbo.ExtendedChild", column 'Child_id'


If the collection only holds the baseclass Child objects it works as expected, but when a derived ExtendedChild is added the delete doesn't seem to propogate to the baseclass. Feel like I'm missing something obvious here but I've still not managed to solve this after a good while searching.

Lastly, I'm also still not 100% clear on the functional differences between Cascade.AllDeleteOrphan and ForeignKeyCascadeOnDelete... or more precisely (ignoring the save/update part) what is the case that the former doesn't handle and requires the latter to be specified? TIA.

Rasmoo

unread,
Aug 7, 2014, 10:43:51 AM8/7/14
to fluent-n...@googlegroups.com
A quick response, from memory and without any form of verification:
 
ForeignKeyCascadeOnDelete means that the RDBMS should manage the cascade delete. AllDeleteOrphan means that NHibernate should manage the cascade delete (and sweep orphans found in memory).
 
So, I suspect that your database schema has a cascade delete on the relation from parent to child, but nothing on the relation between the child and the extended child. The delete will certainly fail if this is the case.
 
I have no idea how to propagate the ForeignKeyCascadeOnDelete all the way down to the extended child, so that everything "just works". Hand-modify the 2nd relation?
 
//Rasmus

Oru Bap

unread,
Aug 11, 2014, 6:23:12 AM8/11/14
to fluent-n...@googlegroups.com
Hi Rasmus,

Many thanks for the reply. That's a much clearer explanation on the differences between those delete options than I found elsewhere. Another user at StackOverflow pointed out much the same and showed that the two cascade options conflicted with the particular unit test I was attempting, specifically, because I was trying to create and delete the parent in the same transaction. Having removed ForeignKeyCascadeOnDelete from the mapping, (and also remembering to add the children to the parent collection before persisting) the test now works as expected.

Thanks for your time.



--
You received this message because you are subscribed to a topic in the Google Groups "Fluent NHibernate" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/fluent-nhibernate/JnxmzHWURBc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to fluent-nhibern...@googlegroups.com.
To post to this group, send email to fluent-n...@googlegroups.com.
Visit this group at http://groups.google.com/group/fluent-nhibernate.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages