Fluent NHibernate:如何创建一对一的双向映射?

发布于 2024-10-28 11:58:05 字数 898 浏览 1 评论 0原文

我有一个类似的问题 Fluent NHibernate: How to create一对多双向映射?但我对一对一映射时的情况感兴趣。例如

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);
}

当创建表时,流畅的将在伞中创建一个引用伞所有者 ID 的字段,并在伞所有者中创建一个引用伞的字段。有没有一种方法可以更改映射,以便仅创建一个外键,但 Umbrella 属性和 Owner 属性都存在?我见过的例子涉及在两个方向上设置关系,因此添加一个新的伞看起来

AddUmbrealla(UmbrellaOwner owner)
{
   var brolly = new Umbrella();
   brolly.Owner = owner;
   owner.Umbrella = brolly;
   session.Save(owner); //assume cascade
 }

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

I had a similar question to Fluent NHibernate: How to create one-to-many bidirectional mapping? but I was interested in the situation when I have a one-to-one mapping. For instance

Umbrealla
  ID
  Owner

UmbreallaOwner
  ID
  Umbrella

As we know each umbrella can only be owned by one person and nobody owns more than one umbrella. In a fluent map I would have something like

UmbrellaMap()
{
   Id(x=>x.ID);
   References<UmbrellaOwner>(x=>x.Owner);
}

UmbrellaOwnerMap()
{ 
   Id(x=>x.ID);
   References<Umbrella>(x=>x.Umbrella);
}

When creating the tables fluent will create a field in umbrella referncing the ID of umbrellaOwner and a field in umbrellaOwner referencing umbrella. Is there any way to change the mapping such that only one foreign key will be created but the Umbrella property and the Owner property will both exist? The examples I have seen involve setting the relations up in both directions so adding a new Umbrella looks like

AddUmbrealla(UmbrellaOwner owner)
{
   var brolly = new Umbrella();
   brolly.Owner = owner;
   owner.Umbrella = brolly;
   session.Save(owner); //assume cascade
 }

which seems logical but a bit cumbersome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

唠甜嗑 2024-11-04 11:58:05

嗯,参考就是参考;一个对象具有对另一个对象的引用。反之则不一定成立。

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

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

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

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;

Well, a reference is a reference; one object has a reference to the other. The reverse is not necessarily true.

In your case, you MIGHT get away with a HasOne relationship. However, HasOne is normally for denormalized data. Say you wanted more info about the owner, but you could not change Owner's schema because other code depended on it. You'd create an AdditionalOwnerInfo object, and create a table in the schema in which the OwnerID field of the table was a foreign key to Owner, and also the primary key of the table.

Ayende recommends a two-sided References() relationship in 99.9% of one-to-one cases, where the second object is conceptually separate from the first, but there is an implicit "I alone own exactly one thing" type of relationship. You can enforce the "one and one only" nature of the reference using a Unique().Not.Nullable() modifier set on the References mapping.

To streamline the referential setup, consider defining one object (UmbrellaOwner) as the "parent" and the other (Umbrella) as the "child", and in the parent's property setter, set the child's parent to the current reference:

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;
    }
  }
}

Now, when you assign the child to the parent, the backreference is automagically set up:

var owner = new UmbrellaOwner{Umbrella = new Umbrella()};
Assert.AreEqual(owner, owner.Umbrella.Owner); //true;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文