Updating child instead of deleting it

≯℡__Kan透↙ 提交于 2019-12-23 02:52:45

问题


Look at the entity -

class Person
{
   int id { get; set; };
   IList<PersonAddress> Addresses { set; get; }
   ...
}

Now while updating person from UI if I just remove some addresses from the list of address then I wand to actually delete the address record from db. currently this is updating the address table setting personId = NULL and not deleting the address record. Does anyone know how to do this. may be some mapping issue.

Here I am adding whole Person class mapping file.

public class PersonMappingOverride : IAutoMappingOverride<Person>
{
    public void Override(AutoMapping<Person> mapping)
    {
        mapping.Schema(Schemas.Common);
        mapping.Table("Person");

        mapping.Map(x => x.FirstName).Not.Nullable();
        mapping.Map(x => x.LastName).Not.Nullable();
        mapping.Map(x => x.DateOfBirth).Nullable();

        mapping.References(x => x.Title);
        mapping.References(x => x.Ethnicity);
        mapping.References(x => x.Language);
        mapping.References(x => x.Religion);
        mapping.References(x => x.Country);
        mapping.References(x => x.Gender).Not.Nullable();

        mapping.References(x => x.LoginDetail);

        mapping.HasMany(x => x.Addresses)
            .ForeignKeyConstraintName("FK_PersonAddress_Person_PersonID")
            .Where("DeletedDate is null")
            .Cascade.AllDeleteOrphan()
            .Cascade.SaveUpdate();

        mapping.HasMany(x => x.TelephoneNumbers)
            .ForeignKeyConstraintName("FK_PersonTelephoneNumber_Person_PersonID")
            .Where("DeletedDate is null")
            .Cascade.AllDeleteOrphan()
            .Cascade.SaveUpdate();

        mapping.HasMany(x => x.EmailAddresses)
            .ForeignKeyConstraintName("FK_PersonEmailAddress_Person_PersonID")
            .Where("DeletedDate is null")
            .Cascade.AllDeleteOrphan()
            .Cascade.SaveUpdate();

        mapping.References(x => x.Photograph);

        mapping.References(x => x.Signature);

        mapping.HasMany(x => x.Photographs)
            .ForeignKeyConstraintName("FK_PersonPhotograph_Person_PersonID")
            .Where("DeletedDate is null")
            .Cascade.AllDeleteOrphan()
            .Cascade.SaveUpdate();

        mapping.HasMany(x => x.Signatures)
            .ForeignKeyConstraintName("FK_PersonSignature_Person_PersonID")
            .Where("DeletedDate is null")
            .Cascade.AllDeleteOrphan()
            .Cascade.SaveUpdate();

        //mapping.HasMany(x => x.JobRoles)
        //    .ForeignKeyConstraintName("FK_PersonJobRole_Person_PersonID");
        mapping.HasMany(x => x.Skills)
            .ForeignKeyConstraintName("FK_PersonSkill_Person");
        mapping.HasMany(x => x.SpokenLanguages)
            .ForeignKeyConstraintName("FK_PersonSpokenLanguage_Person");
        mapping.HasMany(x => x.ForbiddenCentres)
            .ForeignKeyConstraintName("FK_PersonForbiddenCentre_Person");
        mapping.HasMany(x => x.Availabilities)
            .ForeignKeyConstraintName("FK_PersonAvailability_Person");
        mapping.HasMany(x => x.Qualifications)
            .ForeignKeyConstraintName("FK_PersonQualification_Person");

        mapping.IgnoreProperty(x => x.PrimaryEmailAddress);
        mapping.IgnoreProperty(x => x.WorkAddress);
    }
}

This is for PersonAddress mapping:

public class PersonAddressMappingOverride : IAutoMappingOverride<PersonAddress>
{
    public void Override(AutoMapping<PersonAddress> mapping)
    {
        mapping.Schema(Schemas.Common);
        mapping.Table("PersonAddress");
        mapping.References(x => x.Person);
        mapping.References(x => x.Address).Cascade.SaveUpdate().Not.Nullable();
        mapping.References(x => x.AddressType).Not.Nullable();
    }
}

回答1:


EDIT: the fluent mapping added appended below

Let's assume your mapping using <bag> looks like this:

<bag name="address" >
    <key column="PersonId" />
    <one-to-many class="Address"/>
</bag>

This is working, and instructing NHibernate to maintain address collection. If new object is added into the collection, its PersonId column will be updated with relationship to current Person. If some address is removed... its PersonId column will be set to null.

If we want more, we could use cascading:

<bag name="address" cascade="all-delete-orphan"
    <key column="PersonId" />
    <one-to-many class="Address"/>
</bag>

In this case, we do not care only about the relationship, but even about the items inside the collection. Check this mapping for more details: 6.2. Mapping a Collection (a small extract):

(6) cascade (optional - defaults to none) enable operations to cascade to child entities

Now, when we remove the address instance from the collection, it will be also deleted from persistence. But, the steps to do that will be:

  1. Update address and set the PersonId to NULL
  2. Delete the address

To avoid that, we can add another mapping feature: inverse mapping. So, in case, that Address has mapping to Person (many-to-one) we can use this mapping (see inverse="true"):

<bag name="address" cascade="all-delete-orphan" inverse="true">
    <key column="PersonId" />
    <one-to-many class="Address"/>
</bag>

Which could be marked as the most efficient, because all the changes will be executed directly on the Address elements (no intermediate steps)

NOTE: just a small cite from the 6.2:

Note: Large NHibernate bags mapped with inverse="false" are inefficient and should be avoided; NHibernate can't create, delete or update rows individually, because there is no key that may be used to identify an individual row.

EDIT: fluent mapping

base on the mapping you've included in the question, you should adjust the Address mapping this way:

...
mapping.HasMany(x => x.Addresses)
    .ForeignKeyConstraintName("FK_PersonAddress_Person_PersonID")
    .Where("DeletedDate is null")
    .Inverse() // this will cause the direct DELETE to be issued
    .Cascade.AllDeleteOrphan() // this is the only Cascade which should be used
    ;


来源:https://stackoverflow.com/questions/20755311/updating-child-instead-of-deleting-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!