Search code examples
nhibernatenhibernate-3

NHibernate Removing ManyToMany record when deleting parent


i'm working with legacy code(so i'd like to change it as little as possible), and i'm having a little trouble with a many to many relationship here.

Here's what i have:

public class Feature {
   List<Profile> Profiles{get;set;}
}

public class Profile{
   List<FeatureProfile> Features{get;set;}
}

public class FeatureProfile {
   Feature Feat {get;set;}
   Profile Profile {get;set;}
}

and their mapping is like this:

mapper.Class<Feature>(m=>
    m.Bag(x => x.Profiles, bagMap =>
                    {
                        bagMap.Table("FeatureProfile");
                        bagMap.Key(key=>key.Column("FeatureId"));
                        bagMap.Cascade(Cascade.All | Cascade.DeleteOrphans);
                    },map=>map.ManyToMany(manyToMany=>manyToMany.Column("ProfileId")))
);


mapper.Class<Profile>(m=>
    m.Bag(x => x.Features, bagMap =>
                    {
                        bagMap.Key(key=>key.Column("ProfileId"));
                        bagMap.Inverse(true);
                        bagMap.Cascade(Cascade.All | Cascade.DeleteOrphans);
                   })
);

mapper.Class<FeatureProfile>(m=> {
    m.ManyToOne(x => x.Profile, x => x.Column("ProfileId"));
    m.ManyToOne(x => x.Feat, x => x.Column("FeatureId"))
});

What I need is: When I delete a Feature, it's FeatureProfile's get deleted too. Note that I think this probably worked in NHibernate 2.x


Solution

  • My experience is more with XML mapping, but I would say that the below rows could help you anyway. NHibernate provides direct mapping for m:n reletaions (with Pair-table, as in example above). You can totally remove the object FeatureProfile. The relation will be mapped implicitly, and the same will apply when deleting any of both ends (Profile or Feature)

    <class name="Feature"...>
    ... 
    <bag name="Profiles" lazy="true" 
        table="FeatureProfile" cascade="none" >
      <key column="FeatureId" />
      <many-to-many class="Profile" column="ProfileId" />
    </bag>
    ...
    
    <class name="Profile"...>
    ... 
    <bag name="Features" lazy="true" 
        table="FeatureProfile" cascade="none" >
      <key column="ProfileId" />
      <many-to-many class="Feature" column="FeatureId" />
    </bag>
    ...
    

    And in this case, NHibernate has no other way, when deleting Feature, then to delete Pair-table records as well (cannot/should not leave DB inconsistent).

    EDITED: cascade for a bag should be none in this case. delete-orphan would cause really dangerous deletion: not only the pairs but also the ends of that relation.

    EDIT BY OP: Here's what we'd have using Mapping by Code:

    mapper.Class<Profile>(m =>
    {
        m.Bag(x => x.Features, bagMap =>
        {
            bagMap.Table("FeatureProfile");
            bagMap.Key(key=>key.Column("ProfileId"));
            bagMap.Lazy(CollectionLazy.Lazy)
            bagMap.Inverse(false);
            bagMap.Cascade(Cascade.None);
        },map=>map.ManyToMany(manyToMany=>manyToMany.Column("FeatureId")))
    }
    
    mapper.Class<Feature>(m =>
    {
        m.Bag(x => x.Profiles, bagMap =>
        {
            bagMap.Table("FeatureProfile");
            bagMap.Key(key=>key.Column("FeatureId"));
            bagMap.Lazy(CollectionLazy.Lazy)
            bagMap.Inverse(false);
            bagMap.Cascade(Cascade.None);
        },map=>map.ManyToMany(manyToMany=>manyToMany.Column("ProfileId")))
    });