2012-02-02 26 views
2

我有一个对象的层次结构如下:NHibernate的产生多个查询的对象删除子集合在

  • 对象
    • 报告
      • 报告项目

根据这里的其他帖子,我将Report.ReportItems映射设置为Inverse和CascadeAllDeleteOrphan。这使得当我从一个对象中删除一个报表时,它会去掉该报表中的ReportItems。

它这样做的方式效率很低。它基本上是一个Delete ... Where ReportItemID = ?

我见过增加批量大小的建议,以防止在过多的往返中完成此操作,但这似乎是一个马虎的修复。有没有一种方法,使产生的NHibernate这样,而不是查询:

Delete ... Where ReportID = ?

这样,它会执行一个查询,将删除所有ReportItems,而不是每一个ReportItem声明。

在此先感谢。

编辑

我从几个人听说NHibernate的根本不会与标准QueryOver等工作,这样

我决定开始使用HQL来解决这个问题。稍后我会使用一些反射来确保没有使用“魔术串”。

我有想法:

  1. 使用HQL到大规模删除报告项目
  2. 告诉会话刷新对象,因此它可以检测到报告项目都不见了
  3. 然后告诉该会话将删除该报告,并让其清理剩余的信息

虽然这不起作用。你可以看到下面的代码:

Session.CreateQuery("delete ReportItem r where r.Report= :report").SetEntity("report", SelectedReport).ExecuteUpdate() 
Session.Refresh(SelectedReport) 
Object.Reports.Remove(SelectedReport) 
Session.Delete(SelectedReport) 
Session.Update(Object) 

我也曾尝试执行HQL语句后做一个Session.Evict,但NHibernate的不断使用缓存来尝试删除该ReportItems。有关如何做到这一点的任何提示?

+0

我想你可能能够实现这一点使用提取策略。尝试一下... http://knol.google.com/k/nhibernate-chapter-16-improving-performance#16%282E%291%282E%29%28C2%29%28A0%29Fetching_strategies – 2012-02-02 11:25:59

+0

也许我不会不明白 - 但我已经熟悉了获取策略以及它们与SELECT查询的关系。他们会帮助这些DELETE查询吗? – Origin 2012-02-02 15:24:58

+0

是的,我相信。无论如何 - 它不会伤害...... – 2012-02-05 08:15:21

回答

0

经过大量的研究,我发现这根本不可能。您可以使用HQL,原始SQL语句或依靠数据库规则通过强制执行关系来执行删除。但是,没有办法告诉NHibernate根据其所有者的ID删除对象列表。

0

如果您的外键已将删除规则设置为级联,那么您可以告诉NH在删除父项时不会为子项生成DELETE语句。在这种情况下,NH将只为父实体生成DELETE语句。

<bag name="ReportItems" cascade="all-delete-orphan" inverse="true"> 
    <key column="report_id" on-delete="cascade" /> 
    <one-to-many class="ReportItem" /> 
</bag> 
+0

我忘了在我的帖子中提到这个。我知道这也是一种选择,但我不喜欢它。我试图保持数据库不可知性,以便在需要时切换到更多移动解决方案。我不能依靠SQLite来做这种事情。 – Origin 2012-02-05 18:41:23