考虑以下情况:用户有一组香料,每个香料可以是“有货”或“用完”(用布尔运行RunOut属性表示)。
我已经使用像这样的组件
将此关系映射到FluentNHibernatepublic 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引用。
如何以不同方式对其进行建模以避免此删除和重新插入行为?
答案 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<>
。