Correcta asignación NHibernate para un escenario específico (uno-a-muchos / uno-a-uno)
-
22-09-2019 - |
Pregunta
Yo tenía una estructura siguiente:
User has many books in his history
que fue traducido a la siguiente
class User { ICollection<Book> History } // C#
User -> UserHistory (UserId, BookId) -> Book // DB
Ahora quiero añadir una fecha a la historia, creando la siguiente estructura de clases:
class User { ICollection<Read> History }
class Read { Book Book, Date At }
y manteniendo el esquema db casi sin cambios
User -> UserHistory (UserId, BookId, At) -> Book
Quiero mapa Read
a UserHistory
, las preguntas son:
- ¿Qué debo usar como
id
en el mapeo deRead
?UserHistory
clave principal es(UserId, BookId)
. ¿Necesito unid
para NH al trabajo? -
UserHistory -> Book
parece ser un caso deone-to-one
. Cómo especificar el nombre de la columna enBookId
UserHistory
en este caso? No veo un atributo de columna enone-to-one
(y hay una razón para que sea explícito acerca de nombre de la columna).
Solución
En el primer escenario, el UserHistory era simplemente una tabla de asignación para una relación de muchos a muchos y no tenía un objeto propio. Ahora, la tabla UserHistory / Leer clase es una entidad separada por lo que tendrá un identificador de algún tipo. La forma más sencilla es añadir una clave principal ReadId (o UserHistoryId) a la mesa UserHistory.
No es necesario añadir una clave separada y podría utilizar una clave compuesta de identificación de usuario y bookId - pero un usuario puede leer un libro más de una vez? Asumiendo así, entonces también tendría que añadir la columna A a la clave compuesta para que sea único. Esto se pone feo y dará lugar a otros problemas cuando se trata de colecciones, por lo que no vale la pena.
El UserHistory a la relación libro es en realidad una relación muchos-a-uno en lugar de uno-a-uno. Muchos usuarios diferentes pueden leer el mismo libro (y tal vez el mismo usuario puede leer un libro más de una vez). Pensar en muchos-a-uno como una referencia de objeto.
Otros consejos
Pregunta 1: No, no es necesario un id, sólo puede asignar como componente (o elemento compuesto en este caso, donde se encuentra en una lista)
Pregunta 2:. User-historia -> libro no es uno-a-uno, muchos usuarios podrían tener leer el mismo libro con el tiempo, por lo que es muchos-a-uno y se debe asignar de manera
Probablemente la cartografía incompleta miradas de la siguiente manera:
<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: Olvídate de asignaciones one-to-one
. Esto se utiliza muy raramente, cuando se tiene dos tablas que comparten la misma clave principal y están unidos entre sí de esta manera realmente uno-a-uno. En la mayoría de los casos, es necesario many-to-one
, aunque en el mundo real es en realidad uno-a-uno.