开发者

nhibernate criteria projection results in inefficient queries

开发者 https://www.devze.com 2023-03-01 07:36 出处:网络
Please see the following example which is a very simplified version of my code: Dim Criteria = Session.CreateCriteria(Of Person)()

Please see the following example which is a very simplified version of my code:

Dim Criteria = Session.CreateCriteria(Of Person)()
Criteria.SetProjection(Projections.Property("Car"))
return 开发者_Python百科Criteria.List(Of Car)()

This works perfectly, however NHibernate 3.1 creates two queries to fetch the results. Something like:

SELECT CarId FROM Person WHERE blababla

and then for each row:

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

This is not very efficient so i tried:

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

Which does nothing. How can I force NHibernate to make a join on the first query, so I end up with one roundtrip to the MySql server?


When you do Projections.Property("Car") and Car is a many-to-one reference, it just becomes an alias for Projections.Property("Car.Id"). If you want to get the actual Car object you have 2 options:

Option 1: Specify all properties of a car in the projection list.

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

If wheels is another entity list then it gets a lot trickier.

Option 2: Specify the query from the Car standpoint

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

There's also an additional option of not using projections and getting the Person object with a fetched Car object


I found a workaround using a subquery. This will work, but I think this still would be more efficient using a join so my original question still stands. My workaround:

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

精彩评论

暂无评论...
验证码 换一张
取 消