构建真正的动态查询

Building truly dynamic queries

我有一个现有的基于 SQL 的普通查询,我想将其转换为一个或多个 nHibernate 表达式。 SQl 表达式如下所示:

string SQL = "SELECT DISTINCT id FROM basetable ";
List<string> conditions...
if( expression_1 ) {
  SQL += "JOIN table_1 ON ...";
  SqlParameters.Add("fooId", _fooId);
}
...
if( expression_n ) {
  SQL += "JOIN table1 ON ...";
  SqlParameters.Add("barId", _barId);
  conditions.Add("field = @barId");
}
...
SQL += "WHERE " + string.Join(" AND ", conditions.ToArray());

结果将是一个巨大的 SQL 表达式。 是否有机会将这种代码转换为 nHibernate 表达式?在这种情况下,性能没有意义。

这实际上取决于您希望查询的动态程度,但为了给您一个概念,以下内容相当简单并且可以扩展以满足更复杂的要求:

EntityA aAlias = null;
EntityB bAlias = null;
// Build the base query, joining all the tables that you may need
var query = session.QueryOver<EntityA>(() => aAlias)
    .JoinAlias(() => aAlias.ListOfB, () => bAlias);

// Add conditions depending on your requirements, e.g. filter criteria passed from an external source
if (expression1) 
{
    query = query.Where(aAlias.SomeId == someId);
}
if (expression2) 
{
    query = query.WhereRestrictionOn(() => bAlias.SomeOtherId).IsIn(listOfIds)
}
// and so on...
// at the end, just execute the query to get a list of strings or whatever you want
var result = query
    .Select(x => aAlias.Id)
    .List<string>();

根据您的情况,您可以将基础查询(即连接表)的构造放入派生 classes 并将共享条件的代码放入基础 class。在将查询作为参数传递给其他方法时,您只需要记住为 Aliases 使用相同的变量名即可。

我们使用类似的东西来构建基于动态搜索条件的查询,包括日期范围、子查询和分页。