【问题标题】:NHibernate SaveOrUpdate merges child collectionsNHibernate SaveOrUpdate 合并子集合
【发布时间】:2013-11-06 17:10:21
【问题描述】:

我有一个类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

这一切都发生在一个事务中,在完成之前没有任何内容保存在数据库中。

为什么要合并这两个集合?在我看来,它应该到达最后一个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(); 之前,如果刷新没有错误。

【问题讨论】:

  • 在一个事务中多次调用 SaveOrUpdate 是否有真正的原因?
  • #1 是创建保存日志的事物的通用方法的一部分,#4 是可以独立调用的方法,另一个调用 (#2) 是错误的。跨度>
  • 我猜#1 与此并不严格相关,我更想弄清楚为什么 #2 和 #4 合并而不是覆盖。

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


【解决方案1】:

此问题可能与 Journal 映射的样式有关。主要是用于您的收藏的级联设置。如果您有 save-updateall 等级联设置,例如

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

那么发生了什么(使用相似的步骤编号)

  1. ...
  2. 此时,集合包含项目 1,2,3 ...SaveOrUpdate(jurnal) 将执行级联。它还进行级联,即会话知道要持久化的这 3 个项目
  3. Clear() 将清除 IList&lt;&gt; 但没有级联触发器可以从会话中删除这些项目。此时,我们的前 3 个 JournalLines 确实是孤儿。没人关心他们
  4. ...
  5. 由事务触发的Flush() 会将所有 JournalLines 插入 DB

解决方案:将映射改为

cascade="all-delete-orphan"

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

【讨论】:

  • 集合已映射为 AllDeleteOrphan。更奇怪的是,如果在调用集合上的Clear() 之前,我循环遍历它们并手动终止它们对Journal 的引用,它们仍然会被提交,三个带有Journal 的引用而三个没有。这些肯定是孤儿,应该删除。
  • 好的,然后请显示您的映射和代码。因为我只能通过我刚才描述的设置和调用来重现您的问题。有了更多的细节,我们就能找出问题所在。
  • 上面添加了更多内容。
  • 我看到了我预期的代码,这并不奇怪。 (显然您使用了调整后的 sn-ps,描述了原理)。目前可能怀疑是一些隐藏电话...抱歉,没有更好的答案...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多