2009-10-20 54 views
3

我有以下結構:正確的NHibernate映射爲特定方案(一到許多/一個對一)

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 } 

,並保持DB模式幾乎沒有變化

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

我要地圖ReadUserHistory的問題是:

  1. 我應該在Read映射,id使用? UserHistory主鍵是(UserId, BookId)。 NH需要id嗎?
  2. UserHistory -> Book似乎是one-to-one的情況。 在這種情況下如何在UserHistory中指定BookId列名? 我在one-to-one上看不到列屬性(並且我有理由明確列名)。

回答

2

在第一種情況下,UserHistory只是多對多關係的映射表,並沒有適當的對象。現在,UserHistory table/Read類是一個獨立的實體,所以它需要某種類型的標識符。最簡單的方法是將主鍵ReadId(或UserHistoryId)添加到UserHistory表。

您不必添加單獨的密鑰,並且可以在UserId和BookId上使用組合鍵 - 但用戶是否可以多次讀取一本書?假設如此,那麼您還需要將At列添加到組合鍵以使其唯一。這會變得醜陋,並會在處理集合時導致其他問題,所以它不值得。

UserHistory to Book關係實際上是多對一而不是一對一關係。許多不同的用戶可以閱讀同一本書(也許同一個用戶可以多次閱讀一本書)。將多對一看作是對象引用。

+0

謝謝,你說得對多對一。我認爲這些類型關係的標準命名與對象POV有些混淆。 – 2009-10-20 18:43:24

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,即使在現實世界中它實際上是一對一的。

+0

太好了,謝謝你的代碼示例!我在這兩個答案之間被撕裂,但我會接受g。的,因爲他的個人分數較少,他的答案稍早。這是可惜的,因此不允許接受這兩個。 – 2009-10-20 19:01:21