Fluent NHibernate Child collection persistence issues

匿名 (未验证) 提交于 2019-12-03 02:34:02

问题:

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...

回答1:

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 with inverse="true". For these associations, the update is handled by the many-to-one (comment: References in Fluent) end of the association, and so considerations of collection update performance simply do not apply.

6.2. Mapping a Collection

inverse (optional - defaults to false) mark this collection as the "inverse" end of a bidirectional association



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!