nhibernate标准投影导致低效查询

时间:2011-04-27 20:38:08

标签: .net nhibernate criteria projection nhibernate-criteria

请参阅以下示例,该示例是我的代码的简化版本:

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服务器进行一次往返?

2 个答案:

答案 0 :(得分:0)

执行Projections.Property("Car")并且Car是多对一参考时,它只会成为Projections.Property("Car.Id")的别名。如果你想获得实际的Car对象,你有两个选择:

选项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")))

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

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

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

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

答案 1 :(得分:0)

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

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