我现在正在使用NHibernate,并且遇到了一个问题,试图提高我工作的数据带宽效率。
上下文是我正在创建一个数据事件编辑器,它有一个填充了事件的列表视图。这些事件有3种类型,每种都存储在自己的MSSQL表中。
有一个父对象,其中包含这三种事件类型的列表。最初,我只是选择了所有的父母并加载了它下面的事件,但如果你说了20个父母,那么它将运行60个查询左右来加载列表。
我现在更改它只运行3个查询,一个用于选择日期X和日期Y之间的所有事件类型。(此日期在表单上设置了一些日期时间选择器。)
现在,我正在尝试在列表中打印父级的名称,但因为我在nHibernate期间从未访问过父级,所以我只有一个“代理”对象,它会导致崩溃。 Parent对象下面可能有数千个不同的对象,所以我只想加载我需要的东西。
在此期间,为了让它编译,我在nHibernate期间访问该对象。
我获取事件的代码如下:
public IList<MyEvent> GetAllMyEventForAllParentsFromSpecificTimePeriod(
DateTime startTime, DateTime endTime)
{
using (var session = SessionFactorySingleton.OpenSession())
{
var queryOver = session
.QueryOver<MyEvent>()
.Where(re => re.Time <= endTime)
.And(re => startTime <= re.Time)
.OrderBy(re => re.Time).Desc;
var list = queryOver.List();
if (list.Count > 0)
{
foreach (var myEvent in list.Select(myEvent => myEvent.ParentItem.Name)) { }
}
return list;
}
}
到目前为止我发现的是列表加载速度要快得多。
所以我想这里真正的问题是我能做些什么才能实现与访问每个ParentItem.Name以强制它加载它们相同的事情?
更新答案: 由于同事的缘故,我设法提高了效率。
return session
.QueryOver<MyEvent>()
.Where(re => re.Time <= endTime)
.And(re => startTime <= re.Time)
.JoinQueryOver(x => x.ParentItem)
.List();
答案:
foreach (var parent in list.Select(x => x.ParentItem)) { NHibernateUtil.Initialize(parent); }
等同于:
public IList<MyEvent> GetAllMyEventForAllParentsFromSpecificTimePeriod(
DateTime startTime, DateTime endTime)
{
using (var session = SessionFactorySingleton.OpenSession())
{
var list = session
.QueryOver<MyEvent>()
.Where(re => re.Time <= endTime)
.And(re => startTime <= re.Time)
.List();
foreach (var parent in list.Select(x => x.ParentItem)) { NHibernateUtil.Initialize(parent); }
return list;
}
}
答案 0 :(得分:0)
如果您只是所有ParentItem名称,则可以使用select。
var queryOver = session.QueryOver<Parent>()
.Select(p => p.Name))
.List<string>()
答案 1 :(得分:0)
如此处Use NHibernate AliasToBean Transformer launch n+1 query所述,我们有两个选项
第一个解决方案需要一些自定义转换器:
1)How to partially project a child object with many fields in nHibernate
并保持良好的QueryOver API - 这里是如何创建一些扩展方法来支持完全类型别名:
2)Nhibernate Group By and Alias To Bean
第二解决方案(details here或there)
NHibernate可以有效地使用批量提取,也就是说,如果访问一个代理(或集合),NHibernate可以加载几个未初始化的代理。批量提取是懒惰选择提取策略的优化。有两种方法可以调整批处理获取:在类和集合级别上。