如何使用 NHibernate 获取多个深度和广度的对象?
我有一个例子,我需要从数据库加载大约 10 000 个对象。数据模型是这样的:
public class SimulationObject
{
public Container Container {get;set;}
public IList<ResultItem> Results {get;set;}
public IList<PreviewData> PreviewData {get;set;}
...
}
public class ResultItem
{
public IList<SomeDataItem> Items {get;set;}
...
}
public class PreviewData
{
public IList<SomeDataItem> Items {get;set;}
...
}
这意味着我想根据某些查询从数据库中查询SimulationObjects 列表,及其所有属性(引用)和子项。
集合的数量如下:
- SimulationObject - ca 6000 - 1200,具体取决于“where”中的参数
- SimulationObject.Results - ca 5 到 40 个项目
- SimulationObject.Results.Items - ca 0 到2 个项目
- SimulationObject.PreviewData - ca 0 到2 个items
- SimulationObject.PreviewData.Items - 大约 1 到 3 个项目
通常,我会这样做:
var query = from sim in session.Query<SimulationObject>()
where sim.Container.Id == containerId && ...
select sim;
query = query.FetchMany(c => c.Results).ThenFetch(o => o.Items)...
但是,我还需要获取“PreviewData”项目将在我的查询中创建笛卡尔积(意味着 PreviewDataAndSubItemsCount x ResultsAndSubItemsCount 返回的行数),这是非常无效的。另外,由于我需要加载大量 SumulationObjects(如前所述,大约 10000 个),我无法进行延迟加载(10000 个查询......并且还有其他困难,因此这甚至不是考虑的替代方案)。
那么有哪些替代方案呢?您将使用什么策略将完整的对象图加载到内存中?
谢谢。
I have a case where I need to load about 10 000 objects from database. The data model is something like this:
public class SimulationObject
{
public Container Container {get;set;}
public IList<ResultItem> Results {get;set;}
public IList<PreviewData> PreviewData {get;set;}
...
}
public class ResultItem
{
public IList<SomeDataItem> Items {get;set;}
...
}
public class PreviewData
{
public IList<SomeDataItem> Items {get;set;}
...
}
This means that I want to query a list of SimulationObjects from database according to some query, and all of it's properties (references) and subitems.
The quantities of collections are the following:
- SimulationObject - ca 6000 - 1200, depending on parameters in "where"
- SimulationObject.Results - ca 5 to 40 items
- SimulationObject.Results.Items - ca 0 to 2 items
- SimulationObject.PreviewData - ca 0 to 2 items
- SimulationObject.PreviewData.Items - ca 1 to 3 items
Normally, I'd do it like this:
var query = from sim in session.Query<SimulationObject>()
where sim.Container.Id == containerId && ...
select sim;
query = query.FetchMany(c => c.Results).ThenFetch(o => o.Items)...
However, I also need to fetch "PreviewData" items for that would create a Cartesian product in my query (meaning PreviewDataAndSubItemsCount x ResultsAndSubItemsCount amount of rows returned) which is very ineffective. Also, as I need to load a LOT of SumulationObjects (about 10000 as sayd earlier), I cannot do lazy loading (10000 queries..and there are other difficulties too, so this isn't even an alternative to consider).
So what are the alternatives ? What strategy would you use to load a complite object graph into memory ?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Ayende 在此解释了一种执行此操作的方法 (HQL):
http://ayende.com/blog/4367/ eagerly-loading-entity-associations-efficiently-with-nhibernate
我还发现了一篇 StackOverflow 文章,它使用查询:
NHibernate 在复杂对象上使用 Queryover API 进行热切加载 不过,
我非常有兴趣从 hte 社区的其他成员那里获得额外的意见。我认为这是 NH 可以改进的一个领域。
Ayende explains one way to do this here (HQL):
http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate
There was also a StackOverflow article that I came across that does this using QueryOver:
NHibernate Eager Loading with Queryover API on a complex object graph
I would be very interested in getting additional input from the rest of hte community though. I think this is one area in which NH could improve on.