更新使用Fluent NHibernate映射的组件时,请避免使用Delete-and-Reinsert

时间:2012-11-14 08:57:02

标签: nhibernate fluent-nhibernate

考虑以下情况:用户有一组香料,每个香料可以是“有货”或“用完”(用布尔运行RunOut属性表示)。

我已经使用像这样的组件

将此关系映射到FluentNHibernate
public UserMappings()
{
   Id(x => x.Id);
   Map(x => x.FirstName);
   Map(x => x.LastName);
   Map(x => x.Email).Length(255).Unique();
   HasOne(x => x.Credentials).Cascade.SaveUpdate().Fetch.Select();
   HasMany(x => x.Spices)
      .Component(c =>
          {
              c.Map(x => x.RunOut);
              c.References(x => x.BaseSpice).Fetch.Join();
          }).Table("User_Spices").Fetch.Join();

}

上面映射中的“Spices”集合是UserSpice类(值对象):

public class UserSpice
{
    public virtual Spice BaseSpice { get; protected set; }
    public virtual bool RunOut { get; protected set; }

    public static UserSpice Create(Spice baseSpice, bool runOut)
    {
        var userSpice = new UserSpice {BaseSpice = baseSpice, RunOut = runOut};
        return userSpice;
    }
}

这很好用 - 但是当我更新任何组件时(例如,将一个spice更改为RunOut = true),所有用户的香料都会被删除并重新插入。

我理解这种情况正在发生,因为NHibernate无法唯一地识别它应该更新哪个用户 - spice引用。

如何以不同方式对其进行建模以避免此删除和重新插入行为?

2 个答案:

答案 0 :(得分:3)

NHibernate有不同类型的集合。其中一些是从更复杂的映射中获利,例如<list><idbag>。请从有关集合类型问题的文档中阅读本部分:

http://nhibernate.info/doc/nh/en/index.html#performance-collections-mostefficientupdate

简短摘录

  

可以说,索引集合还有一个优势   多个协会或价值集合的集合。   由于ISet的结构,NHibernate永远不会更新   元素“更改”时的行。对ISet的更改始终有效   INSERT和DELETE(各行)。再一次,这个考虑   不适用于一对多的协会。

因此,如果您将使用索引列表(甚至idbag),NHibernate可以了解哪个集合项已更改,甚至可以调用UDPATE

还有另一个问题,您可以在哪里找到如何映射索引列表

Fluent Nhibernate - Mapping a list results in NullReferenceException?

简短摘要:

  

HasMany(x =&gt; x.MyChildren).AsList(x =&gt;   x.Column( “序号”))KeyColumn( “AID”​​)Not.KeyNullable();

答案 1 :(得分:1)

在UserSpice中使用唯一性业务规则实现Equals / GetHashcode,例如BaseSpice相等并将.AsSet()添加到HasMany(x => x.Spices)。 Spices的数据类型必须为ICollection<>Iesi.Collections.Generic.ISet<>extra effort System.Collection.Generic.ISet<>