【问题标题】:nhibernate criteria projection results in inefficient queriesnhibernate 标准投影导致查询效率低下
【发布时间】:2011-04-27 20:38:07
【问题描述】:

请看下面的例子,这是我的代码的一个非常简化的版本:

Dim Criteria = Session.CreateCriteria(Of Person)()
Criteria.SetProjection(Projections.Property("Car"))
return Criteria.List(Of Car)()

这非常有效,但是 NHibernate 3.1 创建了两个查询来获取结果。比如:

SELECT CarId FROM Person WHERE blababla

然后对于每一行:

SELECT color, brand, wheels FROM Car WHERE CarId = ?

这不是很有效,所以我尝试了:

Criteria.CreateAlias("Car", "Car")
Criteria.SetFetchMode("Car", NHibernate.FetchMode.Join)

什么都不做。如何强制 NHibernate 在第一个查询上进行连接,所以我最终会往返于 MySql 服务器?

【问题讨论】:

    标签: .net nhibernate criteria projection nhibernate-criteria


    【解决方案1】:

    当您执行 Projections.Property("Car") 并且 Car 是多对一引用时,它只是成为 Projections.Property("Car.Id") 的别名。如果您想获取实际的 Car 对象,您有 2 个选项:

    选项 1:在投影列表中指定汽车的所有属性。

    Criteria.CreateAlias("Car", "Car")
    Criteria.SetFetchMode("Car", NHibernate.FetchMode.Join)
    Criteria.SetProjection(Projections.Projectionist() _
               .Add(Projections.Property("Car.Color")) _
               .Add(Projections.Property("Car.Brand")))
    

    如果wheels 是另一个实体列表,那么它会变得更加棘手。

    选项 2: 从 Car 的角度指定查询

    Criteria.CreateCriteria(Of Car)()
    Criteria.CreateAlias("Person", "person")
    ... //specify your criteria
    

    还有一个额外的选项,即不使用投影并通过获取的 Car 对象获取 Person 对象

    【讨论】:

    • 感谢您的回答。我知道您的第二种解决方案,但是我的标准比我的示例建议的要复杂得多。这次我不能使用这个解决方案。
    【解决方案2】:

    我找到了使用子查询的解决方法。这会起作用,但我认为使用连接仍然会更有效,所以我原来的问题仍然存在。我的解决方法:

    var cars = s.CreateCriteria<Cars>()
        .Add(Subqueries.PropertyIn("Id",
            DetachedCriteria.For<Person>()
                .Add(Restrictions.Eq("Name","MyName"))
                .SetProjection(Projections.Property("Car.Id"))
            ))
        .List<Cars>();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多