流利的NHibernate Child集合持久性问题 [英] Fluent NHibernate Child collection persistence issues
问题描述
public class CardTemplateMapping:ClassMap< CardTemplate>
{
public CardTemplateMapping()
{
表(cardtemplate);
Id(x => x.Id)
.Column(id)
.GeneratedBy.Native();
HasMany(x => x.CostStructures)
.KeyColumn(cardtemplate_id)
.Cascade.All();
}
}
公共类CostStructureMapping:ClassMap< CostStructure>
{
public CostStructureMapping()
{
表(costtructure);
Id(x => x.Id)
.Column(id)
.GeneratedBy.Native();
引用(x => x.CardTemplate)
.Column(cardtemplate_id);
HasMany(x => x.CostComponents)
.KeyColumn(costtructure_id)
.Cascade.AllDeleteOrphan();
公共类CostStructureComponentMapping:ClassMap< CostStructureComponent>
{
public CostStructureComponentMapping()
{
表(CostStructureComponent);
Id(x => x.Id)
.Column(id)
.GeneratedBy.Native();
引用(x => x.CostStructure)
.Column(costtructure_id);
引用(x => x.ResourceType)
.Column(resourcetype_id);
$ b Nhibernate按照我的意图加载关系。但是映射的两个部分看起来有些奇怪(或者说,或者我的期望是奇怪的)。
$ b $首先:
pre> CostStructure structure = new CostStructure(){CardTemplate = template};
template.CostStructures.Add(structure);
Session.Save(template);
Session.Flush();
这不会保存新的 CostStructure
实例。为什么?第二个:假设我已经加载了一个 CardTemplate
,其中有一个 CostStructure code>包含三个
CostStructureComponent
个实体。现在我想从 CostStructure
中删除 CostStructureComponents
之一。
我试过以下:
costStructure.CostComponents.Remove(component);
component.CostStructure = null;
session.Save(template)
现在,我知道显式删除显式的作品,但不应该 DeleteOrphan
部分也声明现在没有 CostStructure
引用的组件被删除? NHibernate尝试执行以下更新:
pre $ UPDATE CostStructureComponent $ b $ SET金额= @ p0,
coststructure_id = @ p1,
resourcetype_id = @ p2
WHERE id = @ p3;
$ b @ p0 = 1 [类型:Int32(0)],
@ p1 = NULL [类型:Int64(0)],
@ p2 = 5 [类型:Int64 (0)],
@ p3 = 13 [类型:Int64(0)]
难道是Equals / GetHashCode已经被错误地执行了?
对不起,已经很晚了,漫长的一天等等...如果我说的是乱码,请让我知道...
所有答案都隐藏在一个设置 .Inverse()
public CardTemplateMapping()
{
HasMany(x => x.CostStructures)
.KeyColumn(cardtemplate_id)
.Cascade.All()
.Inverse(); //这里是这个设置
在这里:
< pre $ public CostStructureMapping()
{
..
HasMany(x => x.CostComponents)
.KeyColumn(costtructure_id )
.Cascade.AllDeleteOrphan()
.Inverse(); //和HERE以及HasMany()上的所有地方(
尝试查找关于此设置的一些文章,一般:如果映射为逆,NHibernate准备好做更好的SQL语句,因为它正在处理关系的另一端...
一些来源:
19.5.2 。列表,地图,idbags和集合是最有效的集合更新 然而, b
在精心设计的NHibernate领域模型中,我们经常看到大多数集合实际上是
一对多
(评论:流利中的HasMany)与inverse =true
的关联。对于这些关联,更新由关联的多对一
(注释:Fluent中的引用)结尾进行处理,因此注意事项收集更新性能根本不适用。
反向 (可选 - 默认为false)将此集合标记为双向关联的反向结尾
I have the following mapping classes (only the relevant part copied):
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 loads the relations as I intended. But two parts of the Mapping seem a bit weird (either that or my expectations are weird).
First:
CostStructure structure = new CostStructure() { CardTemplate = template };
template.CostStructures.Add(structure);
Session.Save(template);
Session.Flush();
This does not save the new CostStructure
instance. Why?
Second one: Assuming I have loaded a CardTemplate
having a CostStructure
containing three CostStructureComponent
entities. Now I want to remove one of those CostStructureComponents
from the CostStructure
.
I tried the following :
costStructure.CostComponents.Remove(component);
component.CostStructure = null;
session.Save(template)
Now, I know that explicitly deleting explicitly works, but shouldn't the DeleteOrphan
part also assert that the component, now without CostStructure
to reference, is deleted? Instead, NHibernate tries to perform the following update:
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)]
Could it be Equals / GetHashCode have been implemented the wrong way?
Sorry, it's late, been a long day and so forth...If I'm talking gibberish, please let me know...
All the answers are hidden in one setting .Inverse()
public CardTemplateMapping()
{
HasMany(x => x.CostStructures)
.KeyColumn("cardtemplate_id")
.Cascade.All()
.Inverse(); // HERE this setting
And here:
public CostStructureMapping()
{
..
HasMany(x => x.CostComponents)
.KeyColumn("coststructure_id")
.Cascade.AllDeleteOrphan()
.Inverse(); // and HERE and everywhere on HasMany()
Try to find some articles about this setting, but in general: If mapped as inverse, NHibernate is ready to do much better SQL Statements, because it is working with other end of relation...
Some sources:
19.5.2. Lists, maps, idbags and sets are the most efficient collections to update cite:
However, in well-designed NHibernate domain models, we usually see that most collections are in fact
one-to-many
(comment: HasMany in Fluent) associations withinverse="true"
. For these associations, the update is handled by themany-to-one
(comment: References in Fluent) end of the association, and so considerations of collection update performance simply do not apply.
inverse (optional - defaults to false) mark this collection as the "inverse" end of a bidirectional association
这篇关于流利的NHibernate Child集合持久性问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!