cartographie correcte NHibernate pour un scénario spécifique (un à plusieurs / one-to-one)
-
22-09-2019 - |
Question
J'ai eu une structure suivante:
User has many books in his history
qui a été traduit comme suit
class User { ICollection<Book> History } // C#
User -> UserHistory (UserId, BookId) -> Book // DB
Maintenant, je veux ajouter une date à l'histoire, la création de la structure de classe suivante:
class User { ICollection<Read> History }
class Read { Book Book, Date At }
et de garder le schéma db presque inchangé
User -> UserHistory (UserId, BookId, At) -> Book
Je veux la carte Read
à UserHistory
, les questions sont:
- Que dois-je utiliser comme
id
dans la cartographie deRead
? clé primaireUserHistory
est(UserId, BookId)
. Ai-je besoin d'unid
pour NH travailler? -
UserHistory -> Book
semble être un cas deone-to-one
. Comment spécifier le nom de la colonne deBookId
dansUserHistory
dans ce cas? Je ne vois pas un attribut de colonneone-to-one
(et il y a une raison pour moi d'être explicite sur le nom de la colonne).
La solution
Dans votre premier scénario, la UserHistory était simplement une table de correspondance pour plusieurs-à-plusieurs et n'a pas un objet approprié. Maintenant, la table UserHistory / Lire la classe est une entité distincte de sorte qu'il aura besoin d'un identifiant de quelque sorte. La façon la plus simple est d'ajouter une ReadID clé primaire (ou UserHistoryId) à la table de UserHistory.
Vous ne devez pas ajouter une clé séparée et pourrait utiliser une clé composite sur UserId et BookID - mais un utilisateur peut lire un livre plus d'une fois? En supposant oui, alors vous devez également ajouter la colonne A la clé composite pour le rendre unique. Cela devient laid et conduira à d'autres problèmes lorsqu'ils traitent avec des collections, il est donc pas la peine.
Le UserHistory réserver relation est en fait un grand nombre à un plutôt qu'un à un. De nombreux utilisateurs différents peuvent lire le même livre (et peut-être le même utilisateur peut lire un livre plus d'une fois). Pensez à plusieurs à un comme une référence d'objet.
Autres conseils
Question 1: non, vous n'avez pas besoin d'un identifiant, vous ne pouvez mapper comme composant (ou composite élément dans ce cas, où il est dans une liste)
Question 2:. Utilisateur histoire -> livre n'est pas un à un, de nombreux utilisateurs ont pu lire le même livre au fil du temps, il est donc beaucoup à l'un et doit être cartographié de façon
regarde la cartographie probablement incomplète comme suit:
<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: Oubliez les correspondances de one-to-one
. Ceci est utilisé très très rarement, quand vous avez deux tables qui partagent la même clé primaire et sont ainsi reliés entre eux vraiment un à un. Dans la plupart des cas, vous avez besoin many-to-one
, même si dans le monde réel, il est en fait un à un.