Cie*_*iel 3 nhibernate fluent-nhibernate
我可能正在使用这种Future<T>方法完全错误,但我在理解如何优化其使用方面遇到了很多麻烦.所以这是我的简单例子.
三个对象,Member,Player,Character
Member {
Player Player { get; set; }
Player {
IList<Character> Characters { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
所以基本上,一个成员也是一个玩家,一个玩家有很多角色.很简单.(这种抽象的原因是保持Member轻量级,因此它只能用于身份验证和角色,其中更多的重量数据必须附加到Player类.)
那么,我有一个方法,我想查询所有Character的Player.所以我有以下查询设置...
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;
Run Code Online (Sandbox Code Playgroud)
我的想法是,从我对Future<T>工作方式的理解(可能是关闭它将急切加载Player(1:1),它将执行IList<Character>相同数据库之旅的查询,限制为10结果.每次旅行只需1名玩家,每次旅行只需1名会员,每次旅行最多10个字符.
但是nhProf告诉我我正在使用无限请求.有人可以向我解释这里发生了什么吗?我只是误解了这些方法是如何工作的?或者任何人都可以提供一个更可行的例子吗?我不懂HQL所以我不能使用这个CreateCriteria方法.
Flo*_*Lim 10
您问题中的三个查询将执行以下操作:
查询1将获取它可以在数据库中找到的第一个播放器,没有任何where-condition.
查询2将采用它可以找到的前十个字符,同样没有任何where-condition.
查询3将执行三个查询并将第一个与您的where-condition匹配的成员以及相关的Player返回,并返回Member的Player.
如果你想迭代播放器的角色,NHibernate会再次击中DB,因为还没有加载角色.
您的示例可以在没有Futures的单个查询中完成,如下所示:
System.Linq.Expressions.Expression<Func<Member, bool>> model = m => m.Id == 1;
Member mAlias = null;
Player pAlias = null;
Character cAlias = null;
Member member = session.QueryOver<Member>(() => mAlias)
.JoinAlias(m => m.Player, () => pAlias)
.Left.JoinAlias(() => pAlias.Characters, () => cAlias)
.Where(model)
.List().FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
这是一个可以更好地展示期货可以做什么的例子.查询的目标是获取id = 1的客户及其所有订单和订单的详细信息和预订.

现在,如果我们想要将订单及其详细信息和预订一起加载,那么生成的查询将为我们提供笛卡尔积: count(Details) * count(Bookings)
int id = 1;
// define Aliases to use in query and be able to reference joined entities
Customer cAlias = null;
Order oAlias = null;
OrderDetails odAlias = null;
Booking bAlias = null;
// get the Customer and his Orders
var customers = session.QueryOver<Customer>(() => cAlias)
.Left.JoinAlias(o => o.Orders, () => oAlias)
.Where(c => c.Id == id)
.Future<Customer>();
// get the Orders and their Details
var orders = session.QueryOver<Order>(() => oAlias)
.JoinAlias(o => o.Customer, () => cAlias)
.Left.JoinAlias(() => oAlias.Details, () => odAlias)
.Where(() => cAlias.Id == id)
.Future<Order>();
// get the Orders and their Bookings
var orders2 = session.QueryOver<Order>(() => oAlias)
.JoinAlias(o => o.Customer, () => cAlias)
.Left.JoinAlias(() => oAlias.Bookings, () => bAlias)
.Where(() => cAlias.Id == id)
.Future<Order>();
var list = customers.ToList();
Customer customer = list.FirstOrDefault();
Order o1 = customer.Orders.FirstOrDefault();
// iterate through the Details
// normally this would cause N+1 selects, here it doesn't, because we already loaded
foreach (OrderDetails od1 in o1.Details)
{
decimal d = od1.Quantity;
}
Run Code Online (Sandbox Code Playgroud)
我的所有映射都使用延迟加载,我没有在这些查询中指定急切加载.尽管如此,当我运行代码时,在没有笛卡尔积的情况下,我在一次往返中得到了三个SQL查询.这就是期货之美.
| 归档时间: |
|
| 查看次数: |
2084 次 |
| 最近记录: |