更新子项而不是删除它

时间:2013-12-24 05:25:48

标签: asp.net-mvc nhibernate fluent-nhibernate nhibernate-mapping

查看实体 -

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

现在,当我从地址列表中删除一些地址时,从UI更新人员 然后我想从db中删除地址记录。目前,这是更新地址表设置 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);

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

这适用于PersonAddress映射:

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 个答案:

答案 0 :(得分:2)

编辑:添加了流利的映射,附加在

之后

假设您使用<bag>的映射如下所示:

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

这是有效的,并指示NHibernate维护address集合。如果将新对象添加到集合中,则会更新其PersonId列与当前Person的关系。如果删除了某个地址,则其PersonId列将设置为空。

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

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

在这种情况下,我们不仅关心关系,甚至关心集合中的项目。检查此映射以获取更多详细信息:6.2. Mapping a Collection(小提取):

  

(6)cascade(可选 - 默认为none)启用级联到子实体的操作

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

  1. 更新地址并将PersonId设置为NULL
  2. 删除地址
  3. 为避免这种情况,我们可以添加另一个映射功能:逆映射。因此,如果该地址已映射到Person(多对一),我们可以使用此映射(请参阅inverse="true"):

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

    可以将其标记为最有效,因为所有更改都将直接在地址元素上执行(无中间步骤)

    注意:只需从6.2开始:

      

    注意:用inverse =“false”映射的大型NHibernate包效率低,应该避免; NHibernate无法单独创建,删除或更新行,因为没有可用于标识单个行的键。

    编辑:流畅的映射

    根据您在问题中包含的映射,您应该以这种方式调整地址映射:

    ...
    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
        ;