如何在 NHibernate 中强制加载代理对象?
How can I force load a proxy object in NHibernate?
我现在正在使用 NHibernate,在尝试提高我正在处理的数据带宽效率时遇到了一个问题。
上下文是我正在制作一个数据事件编辑器,它有一个填充了事件的列表视图。这些事件有 3 种类型,每种都存储在自己的 MSSQL Table.
有一个父对象,其中包含这 3 种事件类型的列表。最初,我只是 select 加载所有父项并加载其下的事件,但如果你说 20 个父项,那么加载列表将 运行 60 次左右的查询。
我现在已将其更改为 运行 仅 3 个查询,一个到 select 日期 X 和日期 Y 之间的所有事件类型。(这个日期是用一些日期时间选择器设置的形式)。
现在,我也试图在列表中打印父对象的名称,但是因为我在 nHibernate 期间从未访问过父对象,所以我只有一个 'proxy' 对象,它会导致崩溃。 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;
}
}
如果您只是所有 ParentItem 名称,您可以使用 select。
var queryOver = session.QueryOver<Parent>()
.Select(p => p.Name))
.List<string>()
如此处所述,我们有两个选择
- 使用投影
- 使用批量获取
第一个解决方案,需要一些自定义转换器:
1) How to partially project a child object with many fields in nHibernate
并保持良好的 QueryOver API - 以下是如何创建一些扩展方法以支持完全类型别名:
2)
第二个解决方案( or there)
NHibernate can make efficient use of batch fetching, that is, NHibernate can load several uninitialized proxies if one proxy is accessed (or collections. Batch fetching is an optimization of the lazy select fetching strategy. There are two ways you can tune batch fetching: on the class and the collection level.
我现在正在使用 NHibernate,在尝试提高我正在处理的数据带宽效率时遇到了一个问题。
上下文是我正在制作一个数据事件编辑器,它有一个填充了事件的列表视图。这些事件有 3 种类型,每种都存储在自己的 MSSQL Table.
有一个父对象,其中包含这 3 种事件类型的列表。最初,我只是 select 加载所有父项并加载其下的事件,但如果你说 20 个父项,那么加载列表将 运行 60 次左右的查询。
我现在已将其更改为 运行 仅 3 个查询,一个到 select 日期 X 和日期 Y 之间的所有事件类型。(这个日期是用一些日期时间选择器设置的形式)。
现在,我也试图在列表中打印父对象的名称,但是因为我在 nHibernate 期间从未访问过父对象,所以我只有一个 'proxy' 对象,它会导致崩溃。 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;
}
}
如果您只是所有 ParentItem 名称,您可以使用 select。
var queryOver = session.QueryOver<Parent>()
.Select(p => p.Name))
.List<string>()
如此处所述
- 使用投影
- 使用批量获取
第一个解决方案,需要一些自定义转换器:
1) How to partially project a child object with many fields in nHibernate
并保持良好的 QueryOver API - 以下是如何创建一些扩展方法以支持完全类型别名:
2)
第二个解决方案(
NHibernate can make efficient use of batch fetching, that is, NHibernate can load several uninitialized proxies if one proxy is accessed (or collections. Batch fetching is an optimization of the lazy select fetching strategy. There are two ways you can tune batch fetching: on the class and the collection level.