代码之家  ›  专栏  ›  技术社区  ›  Andrey Shchekin

针对特定场景(一对多/一对一)更正nhibernate映射

  •  3
  • Andrey Shchekin  · 技术社区  · 15 年前

    我有以下结构:

    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. 我应该用什么做 id 在映射中 ? 用户历史 主键是 (UserId, BookId) . 我需要一个 身份证件 为了NH工作?
    2. UserHistory -> Book 似乎是一个 one-to-one . 如何指定 BookId 列名称 用户历史 在这种情况下? 在上看不到列属性 一对一 (我有理由明确列名称)。
    2 回复  |  直到 15 年前
        1
  •  2
  •   g .    15 年前

    在第一个场景中,用户历史记录只是一个多对多关系的映射表,没有适当的对象。现在,userhistory表/读取类是一个单独的实体,因此它需要某种类型的标识符。最简单的方法是将主键readid(或userhistoryid)添加到userhistory表中。

    您不必添加单独的键,可以在userid和bookid上使用复合键——但是用户可以多次阅读一本书吗?假设是这样,那么您还需要将at列添加到复合键中,使其唯一。这会变得很难看,在处理收藏品时会导致其他问题,因此不值得这样做。

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

        2
  •  1
  •   Stefan Steinegger    15 年前

    问题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 即使在现实世界中,它实际上是一对一的。