我对Fluent NHibernate: How to create one-to-many bidirectional mapping?提出了类似的问题,但当我有一对一的映射时,我对这种情况很感兴趣。例如
Umbrealla
ID
Owner
UmbreallaOwner
ID
Umbrella
据我们所知,每把伞只能由一个人拥有,没有人拥有一把伞。在流畅的地图中我会有类似的东西
UmbrellaMap()
{
Id(x=>x.ID);
References<UmbrellaOwner>(x=>x.Owner);
}
UmbrellaOwnerMap()
{
Id(x=>x.ID);
References<Umbrella>(x=>x.Umbrella);
}
当创建表格时,将在伞中创建一个字段,引用umbrellaOwner的ID和umbrellaOwner引用伞中的字段。是否有任何方法可以更改映射,以便只创建一个外键但是Umbrella属性和Owner属性都存在?我看到的例子涉及在两个方向上设置关系,所以添加一个新的Umbrella看起来像
AddUmbrealla(UmbrellaOwner owner)
{
var brolly = new Umbrella();
brolly.Owner = owner;
owner.Umbrella = brolly;
session.Save(owner); //assume cascade
}
这似乎合乎逻辑但有点麻烦。
答案 0 :(得分:9)
嗯,参考是参考;一个对象引用另一个对象。反过来不一定正确。
在你的情况下,你可能会逃脱HasOne的关系。但是,HasOne通常用于非规范化数据。假设您想了解有关所有者的更多信息,但您无法更改所有者的架构,因为其他代码依赖于它。您将创建一个AdditionalOwnerInfo对象,并在架构中创建一个表,其中表的OwnerID字段是Owner的外键,也是表的主键。
Ayende建议在99.9%的一对一案例中使用双边References()关系,其中第二个对象在概念上与第一个对象分开,但有一个隐含的“我独自拥有一件事”类型关系。您可以使用引用映射上设置的Unique().Not.Nullable()
修饰符强制执行引用的“仅一个”性质。
为了简化参照设置,可以考虑将一个对象(UmbrellaOwner)定义为“父”,将另一个(Umbrella)定义为“子”,并在父的属性设置器中,将子父的父级设置为当前引用:< / p>
public class Umbrella
{
public virtual string ID { get; set; }
public virtual Owner Owner { get; set; }
}
public class UmbrellaOwner
{
public virtual string ID { get; set; }
private Umbrella umbrella;
public virtual Umbrella Umbrella
{
get{
return umbrella;
}
set{
umbrella = value;
if(umbrella != null) umbrella.Owner = this;
}
}
}
现在,当您将子项分配给父项时,会自动设置反向引用:
var owner = new UmbrellaOwner{Umbrella = new Umbrella()};
Assert.AreEqual(owner, owner.Umbrella.Owner); //true;