针对特定场景的正确 NHibernate 映射(一对多/一对一)

发布于 2024-08-08 05:45:00 字数 890 浏览 8 评论 0原文

我有以下结构:

User has many books in his history

已翻译为以下内容

class User { ICollection<Book> History }       // C#
User -> UserHistory (UserId, BookId) -> Book   // DB

现在我想向历史记录添加一个日期,创建以下类结构:

class User { ICollection<Read> History }
class Read { Book Book, Date At }

并保持数据库模式几乎不变

User -> UserHistory (UserId, BookId, At) -> Book

我想将 Read 映射到 UserHistory,问题是:

  1. Read 映射中我应该使用什么作为 idUserHistory 主键是(UserId, BookId)。我需要 id 才能让 NH 工作吗?
  2. 用户历史记录 -> Book 似乎是一个一对一 的情况。 在这种情况下,如何指定 UserHistory 中的 BookId 列名称? 我在one-to-one 上没有看到列属性(并且我有理由明确列名)。

I had a following structure:

User has many books in his history

which was translated to the following

class User { ICollection<Book> History }       // C#
User -> UserHistory (UserId, BookId) -> Book   // DB

Now I want to add a date to the history, creating the following class structure:

class User { ICollection<Read> History }
class Read { Book Book, Date At }

and keeping db schema almost unchanged

User -> UserHistory (UserId, BookId, At) -> Book

I want to map Read to UserHistory, the questions are:

  1. What should I use as id in mapping of Read? UserHistory primary key is (UserId, BookId). Do I need an id for NH to work?
  2. UserHistory -> Book seems to be a case of one-to-one.
    How to specify the BookId column name in UserHistory in this case?
    I do not see a column attribute on one-to-one (and there is a reason for me to be explicit about column name).

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

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

发布评论

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

评论(2

乄_柒ぐ汐 2024-08-15 05:45:00

在您的第一个场景中,UserHistory 只是一个多对多关系的映射表,并且没有适当的对象。现在,UserHistory 表/Read 类是一个单独的实体,因此它需要某种标识符。最简单的方法是向 UserHistory 表添加主键 ReadId(或 UserHistoryId)。

您不必添加单独的键,并且可以在 UserId 和 BookId 上使用复合键 - 但用户可以多次阅读一本书吗?假设是这样,那么您还需要将 At 列添加到组合键以使其唯一。这会变得丑陋,并且在处理集合时会导致其他问题,所以这是不值得的。

UserHistory 到 Book 的关系实际上是多对一而不是一对一。许多不同的用户可以阅读同一本书(也许同一用户可以多次阅读一本书)。将多对一视为对象引用。

In your first scenario, the UserHistory was simply a mapping table for a many-to-many relationship and didn't have a proper object. Now, the UserHistory table/Read class is a separate entity so it will need an identifier of some sort. The easiest way is to add a primary key ReadId (or UserHistoryId) to the UserHistory table.

You don't have to add a separate key and could use a composite key on UserId and BookId -- but can a user read a book more than once? Assuming so, then you would also need to add the At column to the composite key to make it unique. This gets ugly and will lead to other issues when dealing with collections, so it isn't worth it.

The UserHistory to Book relationship is actually a many-to-one rather than a one-to-one. Many different users can read the same book (and perhaps the same user can read a book more than once). Think of many-to-one as an object reference.

梦冥 2024-08-15 05:45:00

问题 1:不,您不需要 id,您只需将其映射为组件(在本例中为复合元素,它位于列表中)

问题 2:用户历史记录 ->书不是一对一的,许多用户可能随着时间的推移阅读同一本书,因此它是多对一的,应该如此映射。

可能不完整的映射如下所示:

<class name="User">

  <bag name="History" table="UserHistory">
    <key name="UserId">
    <composite-element class="Read">
      <property name="At" />
      <many-to-one name="Book" column="BookId" />
    </composite-element>
  </bag>

注意:忘记一对一映射。当您有两个共享相同主键的表并且通过这种方式真正一对一链接在一起时,这种情况很少使用。在大多数情况下,您需要多对一,即使在现实世界中它实际上是一对一的。

Question 1: no, you don't need an id, you just can map it as component (or composite-element in this case, where it is in a list)

Question 2: User-history -> book is not one-to-one, many users could have read the same book over time, so it's many-to-one and should be mapped so.

Probably incomplete mapping looks as following:

<class name="User">

  <bag name="History" table="UserHistory">
    <key name="UserId">
    <composite-element class="Read">
      <property name="At" />
      <many-to-one name="Book" column="BookId" />
    </composite-element>
  </bag>

Note: Forget about one-to-one mappings. This is used very very rarely, when you have two tables which share the same primary key and are this way linked together really one-to-one. In most cases, you need many-to-one, even if in the real world it is actually one-to-one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文