如何在NHibernate中投影集合
本文关键字:投影 集合 NHibernate | 更新日期: 2023-09-27 18:10:57
是否可以在NHibernate中投影集合?
例如: User
{
UserGuid,
IList<Groups> UserGroups,
}
User userEntity = null;
_session
.StatefulSession.QueryOver(() => userEntity)
.SelectList(list => list
.Select(x => x.UserGuid).WithAlias(() => userEntity.UserGuid)
//How can I project group collection here?
.Select(x => x.Groups).WithAlias(() => userEntity.Groups)
)
.TransformUsing(Transformers.AliasToBean<UserEntity>())
.List();
我们必须将投影视为单个SELECT子句。我们可以用DB来做什么,我们可以用QueryOver
来模拟。因此,在这种情况下,我们可以将User
和Group
连接起来,并从User和Group中投射出很少的属性。最好的目标是一些DTO…
语法可以像这样:
ResultDTO resultDTO = null; // the target to be returned
Group groupEntity = null;
User userEntity = null;
_session.StatefulSession
.QueryOver(() => userEntity)
.JoinAlias(() => userEntity.Groups, () => groupEntity)
.SelectList(list => list
.Select(x => x.UserGuid).WithAlias(() => resultDTO.UserGuid)
// more about User - targeting the ResultDTO
...
// almost the same for Group properties
.Select(x => groupEntity.Name).WithAlias(() => resultDTO.GroupName)
..
)
.TransformUsing(Transformers.AliasToBean<ResultDTO >())
.List();
但是周围有一些问题,实际上有效地不允许这种方法。我们将到达Cartesian product
,因为用户的每一行将乘以它所拥有的组的数量。
Row 1 - User A - Group A
Row 2 - User A - Group B // two rows for a user A
Row 3 - User B - Group B
Row 4 - User B - Group C
解决这个问题的一种方法是跳过SelectList()
(不使用投影),并要求nhibernate使用不同的转换:
_session.StatefulSession
.QueryOver(() => userEntity)
.JoinAlias(() => userEntity.Groups, () => groupEntity)
.TransformUsing(Transformers.DistinctRootEntity)
.List();
不错,有人会说,但这又是错误的。没有有效的分页是可能的,因为每个用户的更多行的效果仍然存在。因此,如果我们输入Take(2)
,我们将只得到用户A。事实上,原因是隐藏的,缩小是在内存中,在。net/应用层端完成的-而不是在DB
建议:一对多关系之间不要使用任何连接。将分离查询与强大的NHibernate特性结合使用:19.1.5。使用批处理抓取
请参见:
- NHibernate QueryOver与Fetch产生多个sql查询和数据库命中
- 这是在NHibernate中急切加载子集合的正确方法吗
- https://stackoverflow.com/questions/18419988/