针对特定场景正确的NHibernate映射(一对多/一对一)
我的结构如下:针对特定场景正确的NHibernate映射(一对多/一对一),nhibernate,one-to-many,one-to-one,many-to-one,Nhibernate,One To Many,One To One,Many To One,我的结构如下: User has many books in his history class User { ICollection<Read> History } class Read { Book Book, Date At } 这被翻译成以下内容 class User { ICollection<Book> History } // C# User -> UserHistory (UserId, BookId) -> Book //
User has many books in his history
class User { ICollection<Read> History }
class Read { Book Book, Date At }
这被翻译成以下内容
class User { ICollection<Book> History } // C#
User -> UserHistory (UserId, BookId) -> Book // DB
我想将Read
映射到UserHistory
,问题如下:
Read
的映射中,我应该使用什么作为id
UserHistory
主键是(UserId,BookId)
。NH需要id
才能工作吗UserHistory->Book
似乎是一对一的例子。
在这种情况下,如何在UserHistory
中指定BookId
列名?
我在一对一的上看不到列属性(我有理由明确说明列名)
在第一个场景中,UserHistory只是多对多关系的映射表,没有合适的对象。现在,UserHistory表/读取类是一个单独的实体,因此它需要某种标识符。最简单的方法是向UserHistory表中添加主键ReadId(或UserHistoryId) 您不必添加单独的键,并且可以在UserId和BookId上使用复合键——但是用户可以多次阅读一本书吗?假设是这样,那么还需要将At列添加到复合键中以使其唯一。这会变得丑陋,在处理集合时会导致其他问题,因此不值得这么做
UserHistory与Book的关系实际上是多对一而不是一对一。许多不同的用户可以阅读同一本书(也许同一个用户可以多次阅读一本书)。将多对一视为对象引用。问题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>
注意:忘记
一对一
映射。当您有两个表共享同一主键并且以这种方式真正一对一地链接在一起时,很少使用这种方法。在大多数情况下,您需要多对一
,即使在现实世界中实际上是一对一。谢谢,您的多对一是正确的。我认为这类关系的标准命名与对象POV有点混淆。太好了,感谢代码示例!我在这两个答案之间左右为难,但我会接受g的答案,因为他的个人得分较低,而且他的答案稍早。很遗憾,我不允许两者都接受。
<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>