[英]Combine workings of Query / QueryOver and DetachedCriteria in NHibernate
In my current project, I started using NHibernate and basically everything works nicely, up to a point, where I need to send complete object tree for some entity to the consumer of my service = everything eagerly loaded and sent from the server. 在我当前的项目中,我开始使用NHibernate,并且基本上一切运行良好,直到需要将某个实体的完整对象树发送给我的服务使用者为止-急切地从服务器加载和发送的所有内容。
And I want my queries to be as fast as possible. 我希望我的查询尽快。
The search criteria is rather simple: the complete newest result object for the specified product and the specified department. 搜索条件非常简单:指定产品和指定部门的完整最新结果对象。
If i call my query like this, I am getting the correct result: (however this produces 3 queries, still, at least I am getting the correct result) 如果我这样调用查询,我将得到正确的结果:(但是这会产生3个查询,至少,我得到了正确的结果)
Result res = session.QueryOver<Result>()
.Where(x => x.Product == product)
.Where(x => x.Department == department)
.OrderBy(x => x.Date).Desc
.Take(1).SingleOrDefault();
However, such result is not eagerly loaded with all the child collections. 但是,并非所有子集合都急切地加载这样的结果。 (and yes, it still creates 3 queries). (是的,它仍然会创建3个查询)。
For I definitelly need all the items of type ResultContent
in Content
populated. 因为我绝对需要在Content
填充所有ResultContent
类型的项目。 ResultContent
has some collections of elements, that have their collections as well. ResultContent
有一些元素的集合,也有它们的集合。 I desperately need all those collections fully populated with all the child elements and child elements of its child elements and so on. 我迫切需要所有这些集合完全填充所有子元素及其子元素的子元素,依此类推。
I played with NHibernate queries nearly whole day now and am nearly achieving correct behavior with query like this: 我现在几乎整天都在处理NHibernate查询,并且几乎可以通过以下查询实现正确的行为:
var resultCriteria = DetachedCriteria.For<Result>();
resultCriteria.SetFetchMode("Product", FetchMode.Eager);
resultCriteria.SetFetchMode("Department", FetchMode.Eager);
resultCriteria.SetFetchMode("Content", FetchMode.Join);
resultCriteria.SetFetchMode("Source", FetchMode.Join);
resultCriteria.SetFetchMode("Content.Numerics", FetchMode.Eager);
resultCriteria.SetFetchMode("Content.Numerics.DataCollection", FetchMode.Join);
resultCriteria.SetFetchMode("Content.Numerics.DataDescription", FetchMode.Join);
resultCriteria.SetFetchMode("Content.Numerics.DataDescription.DescriptionSource", FetchMode.Eager);
resultCriteria.SetMaxResults(5);
var relevantResults = resultCriteria.GetExecutableCriteria(session).List<Result>();
With this approach, I am getting 5 Results, but the Content collection is not populated further than the first element. 通过这种方法,我得到了5个结果,但是Content集合的填充没有超出第一个元素。 And for the DataCollection in Numerics, there only are 5 elements queried, even though it should be somewhere near 500 items pulled. 对于以数字表示的DataCollection,仅查询了5个元素,即使应该拉近500个项目也是如此。
I Played with the FetchModes quite a lot and am starting to think that I will not achieve what I need nowhere near in the future. 我在FetchModes上玩了很多游戏,并且开始认为我将无法实现我将来所需要的东西。 Could you please hint me in the proper direction how I could combine those 2 approaches properly? 您能否向我暗示正确的方向,我如何才能正确组合这两种方法?
Should I use HQL (I never did, so I think I would struggle even more)? 我是否应该使用HQL(我从未使用过,所以我想我会更加努力)?
Note: I googled quite a lot and tried a lot of things, but as far as NHibernate and sql goes, I consider myself quite a noob. 注意:我在Google上搜索了很多,并尝试了很多东西,但是就NHibernate和sql而言,我认为自己是一个菜鸟。 I will try improving my skills, but the time pressure now tends towards asking a question. 我将尝试提高自己的技能,但时间压力现在趋向于提出问题。
The other relevant classes look like this (so that you can see which class holds a collection of what, lots of simplifications applied of course) 其他相关的类如下所示(这样您就可以看到哪个类拥有什么的集合,当然也进行了很多简化)
public class Result
{
public virtual long Id { get; protected set; }
public virtual Product Product { get; set; }
public virtual Department Department { get; set; }
public virtual DateTime Date { get; set; }
public virtual ISet<ResultContent> Content { // getters and setters }
public virtual ISet<ResultSource> Source { // getters and setters }
}
public class Product
{
public virtual short Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string Code { get; set; }
public virtual string Description { get; set; }
}
public class Department
{
public virtual short Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string Code { get; set; }
public virtual string Description { get; set; }
}
public class ResultContent
{
public virtual Result Result { get; set; }
public virtual Numerics Numerics { get; set; }
public virtual long Revision { get; set; }
}
public class Numerics
{
public virtual long Id { get; protected set; }
public virtual string Name { get; set; }
public virtual ISet<DataEntry> DataCollection { //getters and setters }
public virtual ISet<DataDescription> DataDescription { //getters and setters}
}
DataEntry and DataDescription Classes are just holding Id, Date and either string or boolean value. DataEntry和DataDescription类仅包含Id,Date和字符串或布尔值。
hi can you try it , 嗨,你能尝试一下吗,
Result ra = null;
Product pa = null;
Department da = null;
Result res = session.QueryOver<Result>(() => ra)
.JoinAlias(() => ra.Product ,() => pa)
.JoinAlias(() => ra.Department ,() => da)
.Where(() => pa == product)
.Where(() => da == department)
.OrderBy(() => ra.Date).Desc
.Take(1).SingleOrDefault();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.