fluent-nhibernate - fluently - nhibernate documentation
nhibernate fluido HasOne WithForeignKey no funciona (6)
Como señaló eulerfx,
La estructura de la tabla indica que puede haber varios documentos para una tarea.
y Chris declaró:
Al poner una Task_ID en el documento, la relación real es HasMany, pero tiene algún tipo de entendimiento implícito de que solo habrá un documento por tarea.
Por supuesto, esto es correcto, así que lo he revertido, por lo que Task tiene un ID de documento anulable.
Gracias a los dos por su ayuda!
Tiré una moneda por la respuesta aceptada, ¡si pudiera marcar las dos, lo haría!
Siempre que cargue una clase de tarea, la propiedad de documento siempre es nula, a pesar de que hay datos en la base de datos.
Clase de tarea:
public class Task
{
public virtual Document Document { get; set; }
Anulación de asignación de tareas para AutoPersistenceModel:
public void Override(AutoMap<Task> mapping)
{
mapping.HasOne(x => x.Document)
.WithForeignKey("Task_Id");
Como se puede ver de la forma en que se está ejecutando NHProf, la condición de unión es incorrecta, parece que WithForeignKey no surte efecto. De hecho, puedo escribir cualquier cadena en el código anterior y no hace ninguna diferencia.
FROM [Task] this_
left outer join [Document] document2_
on this_.Id = document2_.Id
Debería ser:
FROM [Task] this_
left outer join [Document] document2_
on this_.Id = document2_.Task_Id
Si hackeo los datos en la base de datos para que coincidan los identificadores, entonces los datos se cargan, pero obviamente esto es incorrecto, pero al menos demuestra que carga datos.
Edición: buscar en la fuente nhib fluida para encontrar el XML produce esto:
<one-to-one foreign-key="Task_Id" cascade="all" name="Document" class="MyProject.Document, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
Edición: aquí está el esquema:
CREATE TABLE [dbo].[Document](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Task_Id] [int] NOT NULL,
CREATE TABLE [dbo].[Task](
[Id] [int] IDENTITY(1,1) NOT NULL,
¿Alguien tiene alguna idea?
Gracias
Andrés
Creo que el problema aquí es que la convención "HasOne" significa que está apuntando a la otra cosa (la forma relacional estándar de decir "Many To One" / "One to One"); Al poner una Task_ID en el documento, la relación real es HasMany, pero tiene algún tipo de entendimiento implícito de que solo habrá un documento por tarea.
Lo siento, no sé cómo solucionarlo, pero me interesará ver cuál es la solución (no uso NHibernate ni Fluent NHibernate, pero he estado investigando para usarlo en el futuro). Una solución (de alguien con muy poca idea) sería hacer de Documentos una colección en Tarea, y luego proporcionar una propiedad de Documento que devuelva la primera en la colección (usando una interfaz que oculta la propiedad Documentos para que nadie piense que puede agregar nuevos elementos a ella).
Revisando la documentación y considerando la respuesta de eulerfx, tal vez el enfoque sea algo como:
References(x => x.Document)
.TheColumnNameIs("ID")
.PropertyRef(d => d.Task_ID);
EDIT: Solo para que esta respuesta tenga la solución adecuada: la ruta correcta es actualizar el esquema de la base de datos para que coincida con la intención del código. Eso significa agregar un ID de documento a la tabla de tareas, por lo que existe una relación de muchos a uno entre la tarea y el documento. Si los cambios de esquema no fueran posibles, Referencias () sería la resolución apropiada.
Deberías usar:
Referencias (x => x.Documento, "DocumentIdColumnOnTask")
He estado luchando con el mismo problema de Has One y finalmente encontré que esto funcionó:
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Id(x => x.Id);
HasOne(s => s.Child).Cascade.All();
}
}
public class ChildMap : ClassMap<Model.Child>
{
public ChildMap()
{
Id(x => x.Id);
HasOne(s => s.Parent).Constrained().ForeignKey();
}
}
He intentado esta solución:
sólo en el documento:
mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All();
Me encontré con el mismo problema hoy. Creo que el truco es no usar .ForeignKey (...) con el mapeo .HasOne, sino usar .PropertyRef (...) en su lugar. A continuación se describe cómo defino una relación de persona a persona entre una organización (principal) y su administrador (secundario):
HasOne(x => x.Admin).PropertyRef(r => r.Organisation).Cascade.All();
El administrador tiene una referencia simple a la organización utilizando su clave externa:
References(x => x.Organisation, "ORAD_FK_ORGANISATION").Not.Nullable();
Al recuperar una organización, esto cargará el registro de administración correcto, y en cascada las actualizaciones y eliminaciones.