Skip to main content
 首页 » 编程设计

nhibernate之流畅的 NHibernate : How to create one-to-one bidirectional mapping

2024年12月31日8tuyile006

我对 Fluent NHibernate: How to create one-to-many bidirectional mapping? 有类似的问题但是我对一对一映射的情况很感兴趣。例如

Umbrealla 
  ID 
  Owner 
 
UmbreallaOwner 
  ID 
  Umbrella 

众所周知,每把雨伞只能由一个人拥有,没有人拥有超过一把雨伞。在流畅的 map 中,我会有类似的东西
UmbrellaMap() 
{ 
   Id(x=>x.ID); 
   References<UmbrellaOwner>(x=>x.Owner); 
} 
 
UmbrellaOwnerMap() 
{  
   Id(x=>x.ID); 
   References<Umbrella>(x=>x.Umbrella); 
} 

创建表时,fluent 将在伞中创建一个字段,引用伞所有者的 ID,并在伞所有者中创建一个引用伞的字段。有什么方法可以更改映射,以便只创建一个外键,但 Umbrella 属性和 Owner 属性都将存在?我看到的例子涉及在两个方向上建立关系,所以添加一个新的 Umbrella 看起来像
AddUmbrealla(UmbrellaOwner owner) 
{ 
   var brolly = new Umbrella(); 
   brolly.Owner = owner; 
   owner.Umbrella = brolly; 
   session.Save(owner); //assume cascade 
 } 

这似乎合乎逻辑但有点麻烦。

请您参考如下方法:

嗯,引用就是引用;一个对象引用另一个对象。反过来不一定正确。

在您的情况下,您可能会摆脱 HasOne 关系。但是,HasOne 通常用于非规范化数据。假设您想要有关所有者的更多信息,但您无法更改所有者的架构,因为其他代码依赖于它。您将创建一个 AdditionalOwnerInfo 对象,并在架构中创建一个表,其中表的 OwnerID 字段是 Owner 的外键,也是该表的主键。

Ayende 建议在 99.9% 的一对一情况下使用双向 References() 关系,其中第二个对象在概念上与第一个对象是分开的,但有一种隐含的“我独自拥有一件事”类型的关系。您可以使用 Unique().Not.Nullable() 强制引用的“一对一”性质。在引用映射上设置的修饰符。

为了简化引用设置,请考虑将一个对象 (UmbrellaOwner) 定义为“父”,将另一个 (Umbrella) 定义为“子”,并在父的属性 setter 中,将子的父设置为当前引用:

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;