如何将原生SQLQuery(session.CreateSqlQuery)作为子查询在QueryOver中过滤
如何在NHibernate的QueryOver中使用原生SQL子查询作为IN过滤条件
我来帮你搞定这个问题——你现在的代码直接把CreateSQLQuery实例传给IsIn是行不通的,因为IsIn接收的是内存中的值集合,而不是子查询对象。要把原生SQL查询作为子查询嵌入到QueryOver的IN条件里,需要做两个关键调整,下面是具体的解决方案:
修正后的完整代码
// 1. 将原生SQL查询转换为可作为子查询的DetachedSQLQuery var idSubquery = _session.CreateSQLQuery( "select Id from [dbo].[SomeFunction](:parameter)") .AddScalar("Id", NHibernateUtil.Int64) // 仅映射需要的Id列,比AddEntity更高效 .SetParameter("parameter", folderId) .DetachedCriteria; // 转换为分离查询,供QueryOver作为子查询使用 // 2. 在QueryOver中使用IsInSubquery引用子查询 MyEntity entityAlias = null; var listOfEntities = await _session.QueryOver(() => entityAlias) .WhereRestrictionOn(() => entityAlias.Id) .IsInSubquery(idSubquery) // 用IsInSubquery替代IsIn,传入子查询对象 .OrderBy(() => entityAlias.Name).Asc .ListAsync(cancelToken).ConfigureAwait(false);
关键调整说明
- 用
AddScalar替代AddEntity:因为我们只需要子查询返回的Id列,不需要把结果映射成完整的long实体,AddScalar可以直接指定列名和数据类型,更轻量高效。 - 转换为
DetachedSQLQuery:调用.DetachedCriteria方法可以把普通的SQLQuery转换成NHibernate能识别的分离子查询对象,这样才能被QueryOver嵌入到最终生成的SQL中。 - 使用
IsInSubquery方法:这是QueryOver中处理子查询IN条件的正确API,IsIn方法是用来传入内存中的值列表(比如List<long>)的,而IsInSubquery才接受子查询对象。
这样调整后,NHibernate会自动把你的原生SQL子查询嵌入到最终的SELECT语句的IN子句中,完美实现你想要的过滤效果~
内容的提问来源于stack exchange,提问作者Baloo0ch
相关产品推荐
相关产品推荐

