NHibernate 完全填充部分加载的集合

Posted

技术标签:

【中文标题】NHibernate 完全填充部分加载的集合【英文标题】:NHibernate fully populate a partially loaded collection 【发布时间】:2014-08-29 17:40:36 【问题描述】:

我有一个包含 Project 对象的架构。每个项目都有一个所有者,以及一个额外的 SharePermission 对象集合,其中详细说明了也可以访问该项目的其他用户。 SharePermissions 指向IdentityUser 类型的更详细的用户对象

在这种情况下,我使用以下方法加载ProjectsIEnumerable

 /// <summary>
 /// Gets a collection of projects that a user id has access to view.
 /// </summary>
 public static IEnumerable<Project> GetVisibleByUserFuture(ISession session, int userId)
 
     Project p = null;
     ProjectShare s = null;
     IdentityUser u = null;
     return session.QueryOver<Project>(() => p)
         .Left.JoinAlias(() => p.SharePermissions
                , () => s                // Only join when we are not owner
                , Restrictions.On(() => p.OwnerId).Not.IsIn(new []  userId ))
         .Left.JoinAlias(() => s.User, () => u)
         .Where(() => s.User.UserId == userId || p.OwnerId == userId)
         .Future();
 

您会注意到SharePermissions 部分对连接有限制,因此仅加载该集合的一部分。

稍后我想从之前加载的 IEnumerable 集合中选择一个 Project 并不受限制地加载完整的 SharePermissions 集合。

我不完全确定我应该怎么做。 我要再次加载一个全新的Project 对象吗? 或者我可以重新使用现有的Project 对象并以某种方式告诉 NH 完全填充 SharePermissions 集合吗?

【问题讨论】:

可能想试试NhibernateUtil.Initialize(p.SharePermissions),但我认为它只适用于代理对象,不适用于部分加载的集合。 【参考方案1】:

这种情况下的解决方案是 session.Refresh(project)。如此处所述:

9.2. Loading an object(小引用)

使用 Refresh() 方法可以随时重新加载对象及其所有集合。这在使用数据库触发器初始化对象的某些属性时很有用。

...
session.Refresh(project);

但我建议更改查询。只选择一个根实体项目,使用子查询对其进行过滤,应用批量获取来加载集合

查看这些链接以获取批量获取和子查询示例:

batch fetching overview subquery example NHibernate - Many to Many Query using Junction/Joiner Table

【讨论】:

以上是关于NHibernate 完全填充部分加载的集合的主要内容,如果未能解决你的问题,请参考以下文章

Fluent NHibernate:在映射中急切加载多个集合

如何使用 nhibernate 获取 DTO 成员的集合?

通过代码进行 Nhibernate 一对一映射

为啥这两个 NHibernate 查询会产生不同的结果?

NHibernate - 延迟初始化角色集合失败

NHibernate之(13):初探立即加载机制