使用NHibernate从数据库填充大型树时的表每子类策略

时间:2009-12-08 17:02:55

标签: inheritance nhibernate table-per-class

我正在使用NHibernate加载不同类型的大型对象树。映射是使用每子类表策略实现的。我定义了一个基类“Node”,它只有几个字段(NodeId,ParentId,NodeType)和几个从Node继承并添加自己的字段的子类。

这种方法的实施很简单,我不能抱怨性能。使用单个往返,在几百毫秒内在我的旧机器上填充了一个包含10,000个不同类型对象的大树。但是,有一件事让我担心:这样的策略导致生成一个复杂的查询,其中Node表外部连接到与定义的子类相对应的每个其他表。虽然当不同子类的数量很小时这很好,但如果数量增加,OUTER JOIN的复杂性也会增加。

每个类定义表似乎不是一个优雅的选项,并且从基类中选择数据时会很慢(因为UNION)。其他选项似乎增加了到数据库服务器的往返次数。

那么在填充由不同类型的实体组成的大型树时,您认为什么是最佳实践?有没有比table per-subclass更好的东西?

2 个答案:

答案 0 :(得分:2)

您在这里处理两个问题:

  1. 遍历大型层次结构。

  2. 大对象图。

  3. 两者都是ORM会遇到麻烦的地方。 ORM将成为瓶颈,因此当您遇到瓶颈时,您可能需要支持标准ORM功能并下拉到存储过程来处理繁重的工作。

    使用存储过程,您可以利用SQL的执行计划来解决问题,识别查询慢点并识别索引机会。

      

    来自Nhibernate Documentation(这是一个缓存Nhibernate Forge已关闭)

         

    在瓶颈中使用手工编码的ADO.NET。

         

    在系统的性能关键领域,某些类型的操作   (例如,批量更新/删除)可能   受益于直接的ADO.NET。但   拜托,等到你知道的事情   是一个瓶颈。并且不要假设   直接ADO.NET必然更快。   如果需要直接使用ADO.NET,它   可能值得打开NHibernate   ISession并使用该SQL   连接。这样你仍然可以使用   相同的交易策略和   底层连接提供商。

答案 1 :(得分:2)

为防止加入,您可以使用table-per-classhirarchy策略。然后每个子类都驻留在同一个表中,并用鉴别器列进行区分。

我已经将此方法用于15个子类。

唯一的缺点是你不能在子类的属性上定义非null约束,你必须在代码中处理它。