Nhibernate多态查询 - 没有多态提取的Eager Load关联

时间:2011-10-05 15:40:57

标签: c# nhibernate polymorphic-associations eager-loading

我首先要说的是我已经彻底查看了堆栈溢出,nhusers和文档,以找到我的问题的可能解决方案。

当急切地加载关联时,我需要能够在我的多/未来查询的部分中仅查询基类表(尽管从我做过的研究中我认为这不可能)

我已经开始使用流畅的nhibernate映射现有模式作为概念证明。我已经使用每个子类的表映射了一个继承层次结构(映射都工作得很好,所以我不会将它们全部粘贴在这里)。层次结构有大约15个子类,基类有一些额外的关联。 E.g。

Base
Dictionary<string, Attribute> Attributes
List<EntityChange> Changes

我需要急切地加载两个集合,因为它们是后期处理所需的给定方案,并且懒惰加载它们会导致性能问题。我急切地通过多个/未来的查询加载它们:

    var baseQuery = session.CreateCriteria<Base>("b")
        .CreateCriteria("Nested", JoinType.LeftOuterJoin)
        .CreateCriteria("Nested2", JoinType.LeftOuterJoin)
        .CreateCriteria("Nested2.AdditionalNested", JoinType.LeftOuterJoin);

    var logsQuery = session.CreateCriteria<Base>("b").CreateAlias("Changes", "c", JoinType.LeftOuterJoin,
            Expression.And(Expression.Ge("c.EntryDate", changesStartDate), Expression.Le("c.EntryDate", changesEndDate)))
            .AddOrder(Order.Desc("c.EntryDate"));

    var attributesQuery = session.CreateCriteria<Base>("t").SetFetchMode("Attributes", FetchMode.Join);

    logsQuery.Future<Base>();
    attributesQuery.Future<Base>();
    var results = baseQuery.Future<Base>().ToList();

查询执行并返回正确的结果。但只是以这种方式急切加载关联意味着属性和更改查询必须执行多态获取(每个查询添加大约15个不需要的左外连接)。我知道这是多态查询所必需的,但基本查询将返回我想要的层次结构。发出多态查询的多查询的其他部分是多余的。

我尚未映射整个层次结构,因此将会执行其他不必要的连接,并且还可以预先加载其他关联。这两者结合而不增加体积将导致性能问题。此查询当前的性能大约是6秒(这无疑比它目前正在使用的20更好),但是通过查询并稍微取出额外的连接我可以将其降低到大约2秒(这是一个常见的查询,所以尽可能低,这不仅有利于我。它也将从多个分布式机器运行,所以我宁愿不进入有关缓存/二级缓存的讨论)。

我试过了

  1. 在查询'class = base'中使用class修饰符。我最初是盲目地做到这一点但是相信这是鉴别器价值观。即使它是SQL中的case语句,也不会阻止额外的连接。
  2. 在一个查询中执行所有操作。这比上面拆分更慢并且给出了笛卡尔积
  3. 使用'Polymorphism.Explicit();'在流畅的映射中。这没有效果,因为我使用ClassMap与SubclassMaps,因此它被忽略。我尝试将所有地图更改为ClassMaps并使用Join,但这并未提供所需的行为。
  4. 试图欺骗nhibernate将基类表连接到自身以加载关联(基本上加载一个更具体的类型以防止多态查询) - 创建一个派生类'BaseOnlyLoading',它使用相同的表和主键作为基础类。这显然是一个黑客,但我只是想看看有什么可能。 NHibernate不允许类和子类使用相同的表。
  5. 将BaseOnlyLoadingMap定义为具有与BaseMap相同关联的类映射,并将连接返回到Base。这是有希望的,因为基于完整类型名称在上下文中解析了关联集合。
  6. 使用拦截器修改执行前的SQL。我不会在生产中使用它,只是出于兴趣尝试。我将拦截器传递给本地会话。这导致了问题,我没有继续。
  7. HQL'Type'查询运算符,如here所述,但我不确定它是否已在.NET版本中实现,并且可能与1的行为类似。
  8. 最高评级答案(How to perform a non-polymorphic HQL query in Hibernate?)的评论建议覆盖persister上的IsExplicitPolymorphism。我快速浏览了一下,据我记得,persister是每个实体的全局,或者是来自静态工厂的SessionImpl,这会阻止这样做。即使这是可能的,我也不确定这会产生什么样的副作用。

    我尝试使用一些SQL加载所有内容,但即使我使用存储过程,我也不确定nhibernate如何将图形重新组合在一起。也许我可以指定所有实体和别名?

    指定显式的每个查询会很好。有什么建议吗?

    提前致谢。

0 个答案:

没有答案