在 NHibernate QueryOver 的条件下使用 SelectSubQuery 的结果

Use the result of SelectSubQuery in a condition with NHibernate QueryOver

我正在使用 NHibernate 和 IQueryOver 来检索 List<Message>。用户可以将 Message 标记为收藏夹。每个 Message 都有一个 属性 public bool IsFavourite,当至少有一个 UserMessage 标记为他们的最爱时,其中包含 true。 所以在我的查询中,我使用 SelectSubQuery 来检索它被标记为收藏的次数。到目前为止,一切都很好。我还想在条件中使用该子查询的结果来设置 IsFavourite.

我的查询现在看起来像这样。

Message messageAlias = null;
MessageDTO messageDto = null;

var messages = GetSessionFactory().GetCurrentSession()
    .QueryOver<Message>(() => messageAlias)
    .SelectList(list => list
        .Select(() => messageList.Id).WithAlias(() => messageDto.Id)
        .Select(() => messageList.Title).WithAlias(() => messageDto.Title)
        .SelectSubQuery(
            QueryOver.Of<UserMessageFavourite>()
            .Where(f => f.Message.Id == messageAlias.Id).ToRowCountQuery()).WithAlias(() => messageDto.FavouriteCount)
        )
    )

属性 MessageDto,FavouriteCount 就在那里,所以我可以设置 IsFavourite 属性。所以我想做的是在条件中使用 SubQuery 结果并将该条件的结果设置为 IsFavourite,如 .SelectSubQuery(subquery.ToRowCountQuery()) > 0).WithAlias(() => messageDto.IsFavourite)

如果您的 MessageDTO 实体中已经有 FavouriteCount,那么您可以像这样使用只读 C# 属性:

class MessageDTO {
   //other properties
   public int FavouriteCount { get; set; }
   public bool IsFavorite => FavouriteCount > 0;
}

否则你可以使用自定义投影:

Message messageAlias = null;
MessageDTO messageDto = null;

var projection = Projections.Conditional(
     Subqueries.Exists(QueryOver.Of<UserMessageFavourite>()
                       .Where(f => f.Message.Id == messageAlias.Id).DetachedCriteria)),
     Projections.Constant(true),
     Projections.Constant(false));

var messages = GetSessionFactory().GetCurrentSession()
    .QueryOver<Message>(() => messageAlias)
    .SelectList(list => list
        .Select(() => messageList.Id).WithAlias(() => messageDto.Id)
        .Select(() => messageList.Title).WithAlias(() => messageDto.Title)
        .Select(projection).WithAlias(() => messageDto.IsFavorite)
    )