fluently - Fluidez en los problemas de persistencia de la colección infantil de NHibernate
nhibernate download c# (1)
Todas las respuestas están ocultas en una configuración .Inverse()
public CardTemplateMapping()
{
HasMany(x => x.CostStructures)
.KeyColumn("cardtemplate_id")
.Cascade.All()
.Inverse(); // HERE this setting
Y aquí:
public CostStructureMapping()
{
..
HasMany(x => x.CostComponents)
.KeyColumn("coststructure_id")
.Cascade.AllDeleteOrphan()
.Inverse(); // and HERE and everywhere on HasMany()
Intente encontrar algunos artículos sobre esta configuración, pero en general: si se mapea como inverso, NHibernate está listo para hacer mejores sentencias SQL, porque está trabajando con otro extremo de relación ...
Algunas fuentes:
19.5.2. Las listas, mapas, idbags y conjuntos son las colecciones más eficientes para actualizar :
Sin embargo, en modelos de dominio NHibernate bien diseñados, generalmente vemos que la mayoría de las colecciones son, de hecho, asociaciones de
one-to-many
(comentario: HasMany in Fluent) coninverse="true"
. Para estas asociaciones, la actualización es manejada por el extremo de la asociaciónmany-to-one
(comentario: referencias en fluidez) , por lo que las consideraciones sobre el rendimiento de la actualización de la colección simplemente no se aplican.
inverso (opcional, por defecto es falso) marque esta colección como el extremo "inverso" de una asociación bidireccional
Tengo las siguientes clases de mapeo (solo la parte relevante copiada):
public class CardTemplateMapping : ClassMap<CardTemplate>
{
public CardTemplateMapping()
{
Table("cardtemplate");
Id(x => x.Id)
.Column("id")
.GeneratedBy.Native();
HasMany(x => x.CostStructures)
.KeyColumn("cardtemplate_id")
.Cascade.All();
}
}
public class CostStructureMapping : ClassMap<CostStructure>
{
public CostStructureMapping()
{
Table("coststructure");
Id(x => x.Id)
.Column("id")
.GeneratedBy.Native();
References(x => x.CardTemplate)
.Column("cardtemplate_id");
HasMany(x => x.CostComponents)
.KeyColumn("coststructure_id")
.Cascade.AllDeleteOrphan();
}
}
public class CostStructureComponentMapping : ClassMap<CostStructureComponent>
{
public CostStructureComponentMapping()
{
Table("CostStructureComponent");
Id(x => x.Id)
.Column("id")
.GeneratedBy.Native();
References(x => x.CostStructure)
.Column("coststructure_id");
References(x => x.ResourceType)
.Column("resourcetype_id");
}
}
Nhibernate carga las relaciones como yo quería. Pero dos partes del mapeo parecen un poco raras (o eso o mis expectativas son raras).
Primero:
CostStructure structure = new CostStructure() { CardTemplate = template };
template.CostStructures.Add(structure);
Session.Save(template);
Session.Flush();
Esto no guarda la nueva instancia de CostStructure
. ¿Por qué?
Segundo: Suponiendo que he cargado una CardTemplate
tiene una CostStructure
contiene tres entidades de CostStructureComponent
. Ahora quiero eliminar uno de esos CostStructureComponents
de la CostStructure
.
Intenté lo siguiente:
costStructure.CostComponents.Remove(component);
component.CostStructure = null;
session.Save(template)
Ahora, sé que eliminar explícitamente funciona, pero ¿no debería la parte DeleteOrphan
también afirmar que el componente, ahora sin CostStructure
a referencia, se elimina? En cambio, NHibernate intenta realizar la siguiente actualización:
UPDATE CostStructureComponent
SET amount = @p0,
coststructure_id = @p1,
resourcetype_id = @p2
WHERE id = @p3;
@p0 = 1 [Type: Int32 (0)],
@p1 = NULL [Type: Int64 (0)],
@p2 = 5 [Type: Int64 (0)],
@p3 = 13 [Type: Int64 (0)]
¿Podría ser Equals / GetHashCode se han implementado de la manera incorrecta?
Lo siento, es tarde, ha sido un día largo y demás ... Si estoy hablando de un galimatías, háganmelo saber ...