1

是否可以在 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();
4

1 回答 1

0

我们必须将投影视为单个 SELECT 子句。我们可以在数据库端用它做什么,我们可以用QueryOver. 因此,在这种情况下,我们可以加入Userand 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,因为 User 的每一行将被乘以它所拥有的 Groups 的数量。

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() (不要使用投影)并要求 NHiberante 使用不同的转换:

_session.StatefulSession
    .QueryOver(() => userEntity)
    .JoinAlias(() => userEntity.Groups, () => groupEntity)
    .TransformUsing(Transformers.DistinctRootEntity)
    .List();

不错,有人会说,但这又错了。没有有效的分页是可能的,因为每个用户的更多行的效果仍然存在。所以,如果我们说Take(2),我们只会得到User A。原因实际上是隐藏的,缩小是在内存中,在 .NET/应用程序层端进行的,而不是在数据库中

建议:不要在一对多关系之间使用任何连接。将分离的查询与强大的 NHibernate 功能结合使用:19.1.5。使用批量获取

请另见:

于 2014-07-02T05:29:08.163 回答