4

考虑以下场景:用户有一组香料,每个香料可以是“有货”或“用完”(由布尔 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;
    }
}

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

我知道发生这种情况是因为 NHibernate 无法唯一标识它应该更新的用户香料引用。

如何以不同的方式对此进行建模以避免这种删除并重新插入行为?

4

2 回答 2

3

NHibernate 有不同类型的集合。他们中的一些人从更复杂的映射(如<list>or )中获利<idbag>。请从有关集合类型问题的文档中阅读此部分:

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

短提取物

可以说,索引集合对于多对多关联或值集合具有优于集合的另一个优势。由于 ISet 的结构,NHibernate 不会在元素“更改”时更新一行。对 ISet 的更改始终通过 INSERT 和 DELETE(单个行)进行。再一次,这种考虑不适用于一对多关联。

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

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

Fluent Nhibernate - 映射列表会导致 NullReferenceException?

简短的摘要:

HasMany(x => x.MyChildren).AsList(x => x.Column("Ordinal")).KeyColumn("AId").Not.KeyNullable();

于 2012-11-14T09:25:00.307 回答
1

在 UserSpice 中实现 Equals/GetHashcode 并使用唯一性业务规则,例如 BaseSpice 相等并添加.AsSet()HasMany(x => x.Spices). Spices 的数据类型必须是ICollection<>or Iesi.Collections.Generic.ISet<>,需要额外的努力 System.Collection.Generic.ISet<>

于 2012-11-14T09:12:01.273 回答