views:

168

answers:

2

Further to my other question given the following classes and fluent map, is there any way to automatically cascade delete a DriversLicense when the related Person is deleted? Note, I do not want the Person class to have any knowledge of the DriversLicense class, but I also don't want orphaned data if a Person gets deleted.

public class PersonMap : ClassMap<Person>
{
        public PersonMap() { Id( x => x.Id ); }
}

public class PersonMap : ClassMap<Person>
{
        public PersonMap() { Id( x => x.Id ); }
}

public class DriversLicense
{
        public virtual Person Person { get; set; }
        public virtual string State { get; set; }

        public override bool Equals( object obj ){ ... }
        public override int GetHashCode(){ ... }
}

public class DriversLicenseMap : ClassMap<DriversLicense>
{
        public DriversLicenseMap()
        {
                UseCompositeId().WithKeyReference( x => x.Person );
                Map( x => x.State );
        }
}
A: 

You can't do that with the way you want to structure your objects. If you wanted to added DriversLicense to the Person class you could cascade delete it. But as you already said you don't want the person object to have any knowledge of the DriversLicense.

What you actually need to do is get all of the drivers licenses that contain that person and then delete the DriverLicenses with Cascade delete and that will remove the person record and the license.

(I haven't followed alot of the changes on the FNH stack recently so it's possible it got renamed at some point) You need to alter your map to something similar to:

public DriversLicenseMap()
{
        UseCompositeId().WithKeyReference( x => x.Person ).Cascade.All();
        Map( x => x.State );
}

Edit: With the new information added what you actually need to do is setup in your Repository class where you handle deleting a Person to run a search for all drivers licenses that have that person. Most likely you will need to write a Criteria expression to handle that.

After you get that list you want to delete all of those objects and make sure you flush out those deletes, THEN delete the person record and flush it out.

With the situation you explained about not wanting orphaned data the way you want it constrained and not wanting to have the drivers license class inside the person class it isn't possible to handle with any type of cascade deleting (to my knowledge.)

Chris Marisic
I should have stated earlier that the Person may lose their drivers license, but still remain so I can't cascade the other way. :(
Paul Alexander
A: 

Since you can't cascade deletes from DriversLicense to Person, for business reasons, and you really don't what the Person to know about the DriversLicense and you have a really good reason for this requirement then I think you could handle it in one of two ways:

  1. Move the responsibilty for deleting the DriversLicense object further into your service or repository levels and doing what Chris suggested. Query for a Person's DriverLicnese objects and delete them before you delete the Person entity.

  2. You could create an Nhibernate Interceptor or EventHandler that performs deletes for you. This approach leaves your repositories and domain nice and clean and is probably the approach I would take if I couldn't reference the DriveLicenese collection from my person object. (NHibernate Event Documentation)

Andrew Hanson