3

我有以下结构:

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

我想映射ReadUserHistory,问题是:

  1. 我应该id在映射中使用Read什么?UserHistory主键是(UserId, BookId). 我需要一个idNH 才能工作吗?
  2. UserHistory -> Book似乎是一个案例one-to-one。在这种情况下如何指定BookId列名UserHistory?我没有看到列属性one-to-one(我有理由明确列名)。
4

2 回答 2

2

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

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

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

于 2009-10-20T11:58:20.103 回答
1

问题 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>

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

于 2009-10-20T12:31:09.753 回答