请看下面的例子,这是我的代码的一个非常简化的版本:
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服务器了?
当您执行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")))
如果wheels是另一个实体列表,那么它会变得更加棘手。
选项2:从Car的角度指定查询
Criteria.CreateCriteria(Of Car)()
Criteria.CreateAlias("Person", "person")
... //specify your criteria
还有一个额外的选项,不使用投影,并获得Person对象与获取的Car对象
我找到了一个使用子查询的解决方案。这将工作,但我认为这仍然会更有效地使用连接,所以我原来的问题仍然存在。我的解决方案:
var cars = s.CreateCriteria<Cars>()
.Add(Subqueries.PropertyIn("Id",
DetachedCriteria.For<Person>()
.Add(Restrictions.Eq("Name","MyName"))
.SetProjection(Projections.Property("Car.Id"))
))
.List<Cars>();