NHibernate SaveOrUpdate合并子集合

时间:2013-11-06 17:10:22

标签: c# nhibernate fluent-nhibernate fluent-nhibernate-mapping

我有一个班级Journal,其中有IListJournalLine个对象。

我创建了一个Journal并意外地通过相同的行生成方法两次运行它。此方法的开头调用_journalLines.Clear(),结尾执行_session.SaveOrUpdate(journal)。所以我有这个序列:

  1. 生成Journal没有行,请致电SaveOrUpdate。没关系。
  2. 生成三个JournalLines,ID为1,2,3,添加到Journal._journalLines并致电SaveOrUpdate
  3. 致电Journal._journalLines.Clear()。此后的断点显示行列表为空。
  4. 生成ID为4,5,6的三个JournalLines,添加到Journal._journalLines并致电SaveOrUpdate。这里的断点显示_journalLines包含三个内容。
  5. 我留下了{6}的Journal
  6. 这一切都发生在一个事务中,数据库中没有任何内容持续存在,直到它完成。

    为什么这两个合并?在我看来它应该到达最后SaveOrUpdate,其中断点显示它有三行,并坚持它有三行。其他三个在某个地方的内存中闲逛,因为还没有冲洗吗?

    编辑:制图

    public JournalMap()
    {
        // Other stuff
        HasMany(x => x.JournalLines)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.AllDeleteOrphan();
    }
    
    public JournalLineMap()
    {
        // Other stuff
        References(x => x.Journal);
    } 
    

    Journal有以下内容:

    private readonly IList<JournalLine> _journalLines = new List<JournalLine>();
    public virtual IEnumerable<JournalLine> JournalLines 
                                           { get { return _journalLines; } }
    

    生成行的实际代码太复杂了,无法在此处添加,但在生成后调用_journalLines.Add(journalLine);,然后调用它,T为Journal

     public T Add(T entity)
     {
         _session.SaveOrUpdate(entity);
         return entity;
     }
    

    在最终调用_session.Flush()_session.Transaction.Commit();之前,如果刷新没有错误。

1 个答案:

答案 0 :(得分:1)

此问题可能与 Journal 映射的样式有关。主要是用于您的收藏的级联设置。如果您要进行级联设置,例如保存更新全部,例如

<bag name="JournalLines" lazy="true" inverse="true" cascade="save-update"
 ...

然后发生了什么(使用类似的步骤编号)

  1. ...
  2. 此时,该集合包含项目1,2,3 ... SaveOrUpdate(jurnal)将执行级联。它也进行级联,即会话知道要保留这3个项目
  3. Clear()将清除IList<>,但没有级联触发器可以从会话中删除这些项目。在这一刻,我们的前3个JournalLines真的是孤儿。没有人关心他们
  4. ...
  5. 由事务触发的
  6. Flush()将所有JournalLines插入到数据库
  7. 解决方案:将映射更改为

    cascade="all-delete-orphan"
    

    注意:从上面提供的定义来看,我猜这是场景(我刚才解释过) 如果您致电session.SaveOrUpdate(eachJournalLine),可能会遇到其他问题。在这种情况下Clear()是不够的,你还必须迭代所有删除的项目并将它们的关系设置为line.Journal = null