在NHibernate中加载复杂图 [英] Loading complex graph in nhibernate
问题描述
想象一下,我有一个非常复杂的模型图,例如:
Imagina i have pretty complex model graph such as for an example:
Orchestra -> Musicians -> Instruments -> Properties
-> Items
-> Songs -> Parts
理论上,我知道期货的运作方式,但是我如何加载完整的图表,可以让具体的音乐家(由id指定)说
I know in theory how Futures works but how do i load this complete graph lets say for a concrete musician (specified by id).
我知道,对于同一级别的每个集合,我都必须创建一个简单的将来查询,以避免在同一查询中使用笛卡尔积. 所以当我执行这样的代码时:
I know that for each collection on same level i have to create simple one future query to avoid Cartesian product in same query. so when i execute code like this:
using(var session = GetSession()){
var instrumentQuery = session.QueryOver<Musicians>()
.Where(x=>x.Id == CONCRETEMUSICIANIDTHERE)
.JoinQueryOver<Instruments>(x=>x.Instruments)
.Future();
var instrumentProperties = = session.QueryOver<Musicians>()
.Where(x=>x.Id == CONCRETEMUSICIANIDTHERE)
.JoinQueryOver<Instrument>(x=>x.Instruments, ()=> instrumentAlias)
.JoinQueryOver<Property>(()=>instrumentAlias.Properties)
.Future();
var instrumentItems = = session.QueryOver<Musicians>()
.Where(x=>x.Id == CONCRETEMUSICIANIDTHERE)
.JoinQueryOver<Instrument>(x=>x.Instruments, ()=> instrumentAlias)
.JoinQueryOver<Item>(()=>instrumentAlias.Items)
.Future();
...
...CONTINUE same future queries for each unique collection
...
...
var result = session.QueryOver<Musician>()
.Where(x=>x.Id == CONCRETEMUSICIANIDTHERE)
.SingleOrDefault<Musician>(); //This query is not future so it should???? load all futures ???
return result;
}
但是即使最后一个查询不在将来,它也不会将那些FUTUR..ISH查询发送到数据库(我使用SQL事件探查器进行了检查……没有这样的SQL标题发送到数据库)
But even when the last query is NOT future it wont send those FUTUR..ISH queries to DB ( i checked with SQL profiler... there is no such SQL heading to DB)
musician.instrument仍然抛出惰性初始化异常.
musician.instrument still throws lazy initialization exception.
此代码仅是说明性的,并且仅是理论上的.
This code is only demostrative and purely theoretical.
我要避免的是:
- 使用HQL(我讨厌那些魔术弦...)
- 更改映射以热切地加载所有内容,因为在某些用例中,我只需要音乐家和乐器? (或任何其他子集)
- 在这里避免N + 1个查询问题
- 将会话保持打开状态的时间过长,因为这些数据可能会与其他服务器实例发生变化
我想实现的目标
- 要么强制休眠,要么根据提供的标准恰当地创建和构造对象结构.
或
- 强制nhibernate仅对此查询使用访存选择
还有一个类似的问题: 如何使用NHibernate加载大型,复杂的对象图
there is also simmilar question: How to load a large, complex object graph using NHibernate
答案是...更改您的映射...我不想要,因为我看不到每次使用强制转换(甚至是简单使用)都加载此复杂图形的要点
and the answer is... Change your mappings... which i dont want because i dont see a point to load this complex graph for each use cast (even the simple ones)
技术背景:
- 我们使用Nhibernate 4.0
- 作为数据库,可能会使用Azure数据库或SQL Server(或也许使用postgreSQL)
推荐答案
我会说,这里的方式是
- 使用
Fetch
代替 JoinQuery 和 - 也将最终结果放入
Future
- to use
Fetch
instead of JoinQuery and - place final result into
Future
as well
这将是更新的代码段:
var instrumentQuery = session.QueryOver<Musicians>()
.Where(x=>x.Id == CONCRETEMUSICIANIDTHERE)
.Fetch(x=>x.Instruments).Eager
.Future();
var instrumentProperties = = session.QueryOver<Musicians>()
.Where(x=>x.Id == CONCRETEMUSICIANIDTHERE)
.Fetch(x=>x.SecondCollection).Eager
.Future();
...
...CONTINUE same future queries for each unique collection
...
...
var result = session.QueryOver<Musician>()
.Where(x=>x.Id == CONCRETEMUSICIANIDTHERE)
// all will be fetaures
.Future()
.SingleOrDefault<Musician>();
注意:我会采取不同的方式.仅加载根对象(音乐家).使用批量大小进行优化抓取.会话打开时创建DTO.
NOTE: I would go different way. Load just root object (Musician). Use batch-size for optimized fetching. Create DTO while session is open.
这篇关于在NHibernate中加载复杂图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!