特定のシナリオのためのNhibernateマッピングを修正します(1対1/1対1)
-
22-09-2019 - |
質問
次の構造がありました:
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
マッピングしたいです Read
に UserHistory
, 、質問は次のとおりです。
- として何を使用すればよいですか
id
のマッピングRead
?UserHistory
主キーはです(UserId, BookId)
. 。必要ですかid
NHが機能するために? UserHistory -> Book
のケースのようですone-to-one
。指定する方法BookId
列名UserHistory
この場合?列属性が表示されませんone-to-one
(そして、私が列名を明示する理由があります)。
解決
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.
他のヒント
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.