更新孩子而不是删除它 [英] Updating child instead of deleting it

查看:150
本文介绍了更新孩子而不是删除它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class Person 
{
int id {get;组; };
IList< PersonAddress>地址{set;得到; }
...
}

只是从地址
列表中删除一些地址,然后我真的从数据库中删除地址记录。目前这是更新地址表设置 personId = NULL ,而不是删除地址记录。有谁知道如何做到这一点。可能是一些映射问题。

这里我添加整个 Person 类映射文件。

  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);
$ b $ map.HasMany(x => x.Addresses)
.ForeignKeyConstraintName(FK_PersonAddress_Person_PersonID)
.Where(DeletedDate is null)
.Cascade .AllDeleteOrphan()
.Cascade.SaveUpdate();
$ b 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);




$ p $这是用于 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();


$ / code $ / pre

解决方案

em>编辑:添加下面的流利映射



我们假设您使用< bag> 看起来像这样:

 < bag name =address> 
< key column =PersonId/>
<一对多等级=地址/>
< / bag>

这是行得通的,并指示NHibernate维护地址 PersonId 列将更新为与当前Person关系。如果删除了某个地址,那么它的 PersonId 列将被设置为null。



如果我们需要更多,我们可以使用级联:

 < bag name =addresscascade =all-delete-orphan
< key column =PersonId/>
<一对多等级=地址/>
< / bag>

在这种情况下,我们不关心关系,而是关心集合中的项目。请查看此映射以了解更多详情: 6.2。映射集合(小提取):

lockquote
cascade(可选 - 默认为none)使操作级联给子实体

现在,当我们从集合中移除地址实例时,它也将被从持久性中删除。但是,这样做的步骤是:
$ b $ ol

  • 更新地址并设置 PersonId 为空

  • 删除地址


    :逆映射。因此,如果该地址映射到Person(多对一),我们可以使用这个映射(见 inverse =true):

     < bag name =addresscascade =all-delete-orphaninverse =true> 
    < key column =PersonId/>
    <一对多等级=地址/>
    < / bag>

    哪个可以被标记为最有效的,因为所有的改变将直接在Address元素上执行(没有中间步骤)



    注意:只是从6.2中引用一点:


    注意:用inverse =false映射的大型NHibernate包效率低下,应该避免; NHibernate不能单独创建,删除或更新行,因为没有可用于识别单个行的密钥。

    编辑:流利的映射

    在这个问题中,你应该这样调整地址映射:

    $ $ $ $ $ $ $ $ $ $ $映射。 > x.Addresses)
    .ForeignKeyConstraintName(FK_PersonAddress_Person_PersonID)
    .Where(DeletedDate is null)
    .Inverse()//这将导致直接删除
    .Cascade.AllDeleteOrphan()//这是应该使用的唯一级联
    ;


  • 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();
        }
    }
    

    解决方案

    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
        ;
    

    这篇关于更新孩子而不是删除它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆