nHibernate Future,加载顺序混乱
我可能使用 Future
方法完全错误,但我在理解如何优化其使用方面遇到了很多困难。这是我的简单例子。
三个对象,Member
、Player
、Character
Member {
Player Player { get; set; }
Player {
IList<Character> Characters { get; set; }
}
所以基本上,一个成员也是一个玩家,一个玩家有多个角色。够简单的。 (这种抽象的原因是保持 Member
轻量级,以便它只能用于身份验证和角色,其中更重的数据必须附加到 Player
类。 )
那么,我有一个方法,我想查询 Player
拥有的所有 Character
。所以我设置了以下查询...
session.QueryOver<Player>()
.Fetch(context => context.Characters).Eager
.Take(1)
.Future<Player>();
session.QueryOver<Character>()
.Future<Character>()
.Take(10);
return session.QueryOver<Member>()
.Where(model)
.Fetch(context => context.Player).Eager
.List()
.Take(1)
.SingleOrDefault()
.Player;
我的想法是,根据我对 Future
工作方式的理解(这可能很遥远,因为它会急切加载 Player
(1:1),它将在同一数据库行程中执行对 IList
的查询,限制为 10 个结果,每个 Player 只需要 1 个。行程,每次行程最多 10 个字符,
但是 nhProf
告诉我我正在使用无限制的请求,有人可以向我解释一下这是怎么回事吗?这些方法是如何工作的?或者有人可以提供一个更可行的示例吗?我不明白 HQL,所以我无法使用 CreateCriteria 方法。
I may be using the Future<T>
method outright wrong, but I'm having a lot of trouble understanding how to optimize its use. So here is my simple example.
Three objects, Member
, Player
, Character
Member {
Player Player { get; set; }
Player {
IList<Character> Characters { get; set; }
}
So basically, one member is also one player, and one player has many characters. Simple enough. (the reason for this abstraction is to keep Member
lightweight, so that it can be used only for authentication and roles, where more heavy data has to attach to the Player
class.)
So then, I have a method where I want to query all Character
that a Player
has. So I have the following query set up...
session.QueryOver<Player>()
.Fetch(context => context.Characters).Eager
.Take(1)
.Future<Player>();
session.QueryOver<Character>()
.Future<Character>()
.Take(10);
return session.QueryOver<Member>()
.Where(model)
.Fetch(context => context.Player).Eager
.List()
.Take(1)
.SingleOrDefault()
.Player;
My thought here is that, from what I understand about the way Future<T>
works (which may be way off is that it will eager load Player
(1:1), which will perform the query for the IList<Character>
in the same database trip, with a limit of 10 results. It will only take 1 Player per trip, and 1 Member per trip, and up to 10 characters per trip.
However nhProf
is telling me I am using an unbounded request. Can someone explain to me what is going on here? Am I just misunderstanding how these methods work? Or can anyone provide an example that is a bit more viable? I don't understand HQL so I can't use the CreateCriteria
method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您问题中的三个查询将执行以下操作:
查询 1 将获取它可以在数据库中找到的第一个玩家,没有任何 where 条件。
查询 2 将获取它可以找到的前十个字符,同样不带任何 where 条件。
查询 3 将执行这三个查询,并获取第一个与您的 where 条件匹配的成员以及关联的玩家,并返回该成员的玩家。
如果你想迭代玩家的角色,NHibernate 会再次访问数据库,因为还没有加载任何角色。
您的示例可以在没有 Futures 的情况下在单个查询中完成,如下所示:
这是一个示例,可以更好地展示 Futures 的功能。查询的目标是获取 id = 1 的客户及其所有订单以及订单的详细信息和预订。
现在,如果我们想将订单及其详细信息和预订一起加载,生成的查询将为我们提供笛卡尔积:
count(Details) * count(Bookings)
我的所有映射都使用延迟加载,并且我没有在这些查询中指定急切加载。尽管如此,当我运行代码时,我在一次往返中得到了三个 SQL 查询,而没有笛卡尔积。这就是期货的美妙之处。
The three queries in your question will do the following:
Query 1 will take the first Player it can find in the database, without any where-condition.
Query 2 will take the first ten Characters it can find, again without any where-condition.
Query 3 will execute the three queries and take the first Member matching your where-condition, along with the associated Player, and return the Member's Player.
If you wanted to iterate through the Player's Characters NHibernate would hit the DB again, since no Characters had been loaded, yet.
Your example could be done in a single query without Futures like this:
Here is an example that may show better what Futures can do. The goal of the queries is to get the Customer with id = 1 and all his Orders and the Orders' Details and Bookings.
Now, if we want to load the Orders with their Details and Bookings together the resulting query would get us a cartesian product:
count(Details) * count(Bookings)
All my mappings work with lazy loading and I did not specify eager loading in those queries. Still, when I run the code, I get exactly three SQL queries in one roundtrip without a cartesian product. That's the beauty of Futures.