La corretta mappatura NHibernate per uno scenario specifico (uno-a-molti / one-to-one)
-
22-09-2019 - |
Domanda
Ho avuto un seguente struttura:
User has many books in his history
che è stato tradotto al seguente
class User { ICollection<Book> History } // C#
User -> UserHistory (UserId, BookId) -> Book // DB
Ora voglio aggiungere una data alla storia, creando la seguente struttura di classe:
class User { ICollection<Read> History }
class Read { Book Book, Date At }
e mantenendo lo schema db pressoché invariato
User -> UserHistory (UserId, BookId, At) -> Book
Voglio mappare Read
a UserHistory
, le domande sono:
- Cosa devo usare come
id
nella mappatura diRead
? chiave primariaUserHistory
è(UserId, BookId)
. Ho bisogno di unid
per NH funzionare? -
UserHistory -> Book
sembra essere un caso dione-to-one
. Come specificare il nome della colonnaBookId
inUserHistory
in questo caso? Non vedo un attributo di colonnaone-to-one
(e non v'è un motivo per me di essere espliciti nome della colonna).
Soluzione
Nel tuo primo scenario, l'UserHistory era semplicemente una tabella di mappatura per una relazione molti-a-molti e non ha avuto un oggetto proprio. Ora, la tabella di UserHistory / Leggi classe è un'entità separata in modo che avrà bisogno di un identificatore di qualche tipo. Il modo più semplice è quello di aggiungere una ReadId chiave primaria (o UserHistoryId) alla tabella UserHistory.
Non è necessario aggiungere una chiave separata e potrebbe utilizzare una chiave composito su userid e BookID - ma può un utente di leggere un libro più di una volta? Assumendo così, allora si avrebbe anche bisogno di aggiungere la colonna A della chiave composta per renderlo unico. Questo diventa brutto e porterà ad altri problemi quando si tratta di collezioni, quindi non vale la pena.
L'UserHistory prenotare rapporto è in realtà una relazione molti-a-uno, piuttosto che un uno-a-uno. Molti utenti diversi possono leggere lo stesso libro (e forse lo stesso utente può leggere un libro più di una volta). Pensate a molti-a-uno come un riferimento a un oggetto.
Altri suggerimenti
Domanda 1: no, non è necessario un ID, si può solo mappare come componente (o composito-elemento, in questo caso, dove è in una lista)
Domanda 2:. User-storia -> libro non è uno-a-uno, molti utenti avrebbero potuto leggere lo stesso libro nel corso del tempo, quindi è molti-a-uno e dovrebbero essere mappati in modo
Probabilmente la mappatura incompleta appare come segue:
<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>
Nota: Dimenticare mappature one-to-one
. Questo è usato molto raramente, quando si hanno due tabelle che condividono la stessa chiave primaria e che sono in questo modo collegati tra loro davvero uno-a-uno. Nella maggior parte dei casi, è necessario many-to-one
, anche se nel mondo reale è in realtà uno-a-uno.