【问题标题】:PredicateBuilder ignored in LinqToSQL在 LinqToSQL 中忽略 PredicateBuilder
【发布时间】:2014-12-23 22:59:36
【问题描述】:

我已将一个查询传递给我的服务,并将其序列化为一组类。此对象在树状结构中定义条件,以支持无限深度的 AND/ORing 数据。然后我使用 LinqToSQL 将此类转换为 SQL 查询,但是我的条件(使用 PredicateBuilder 定义)被忽略了!

PredicateBuilder 似乎是一个显而易见的解决方案,我的递归函数建立在 Expression<Func<Error,bool>> 而不是 IQueryable<Error> 以支持这一点,我递归地遍历树并适当地附加 AND/OR 条件。

我如下调用递归过滤器,调试时我可以看到递归函数正确返回过滤器 - 我的问题是这些条件被忽略并且不会出现在输出 SQL 中(请参见下文)任何人都可以提出原因这可能是?

如果需要任何其他信息,或者您认为这种方法应该可行,请告诉我。

if ( hasConditions )
{
    results.Where( RecursiveHandleFilterExpression( query.Criteria ) );
}

这是附加谓词的函数

private Expression<Func<Error, bool>> RecursiveHandleFilterExpression( FilterExpression filterExpression )
{
    // if anding, start with true Ors start with false
    Expression<Func<Error, bool>> predicate;
    if ( filterExpression.FilterOperator == LogicalOperator.And )
    {
        predicate = PredicateBuilder.True<Error>();
    }
    else
    {
        predicate = PredicateBuilder.False<Error>();
    }

    // apply conditions
    foreach ( ConditionExpression condition in filterExpression.Conditions )
    {
        if ( filterExpression.FilterOperator == LogicalOperator.And )
        {
            predicate.And( ApplyCondition( condition ) );
        }
        else
        {
            predicate.Or( ApplyCondition( condition ) );
        }
    }

    // apply child filters
    foreach ( FilterExpression expression in filterExpression.Filters )
    {
        if ( filterExpression.FilterOperator == LogicalOperator.And )
        {
            predicate.And( RecursiveHandleFilterExpression( expression ) );
        }
        else
        {
            predicate.Or( RecursiveHandleFilterExpression( expression ) );
        }
    }

    return predicate;
}

生成的 SQL,通过DataContext.Log 属性获取,缺少为 LoggedOn 列传递的 2 个查询

SELECT [t2].[ErrorId], [t2].[OrganisationId], [t2].[Severity], [t2].[Source], [t2].[ExceptionMessage], [t2].[InnerExceptionMessage], [t2].[Details], [t2].[LoggedOn]
FROM (
    SELECT [t1].[ErrorId], [t1].[OrganisationId], [t1].[Severity], [t1].[Source], [t1].[ExceptionMessage], [t1].[InnerExceptionMessage], [t1].[Details], [t1].[LoggedOn], [t1].[ROW_NUMBER]
    FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ErrorId], [t0].[OrganisationId], [t0].[Severity], [t0].[Source], [t0].[ExceptionMessage], [t0].[InnerExceptionMessage], [t0].[Details], [t0].[LoggedOn]) AS [ROW_NUMBER], [t0].[ErrorId], [t0].[OrganisationId], [t0].[Severity], [t0].[Source], [t0].[ExceptionMessage], [t0].[InnerExceptionMessage], [t0].[Details], [t0].[LoggedOn]
        FROM [dbo].[Errors] AS [t0]
        WHERE [t0].[OrganisationId] = @p0
        ) AS [t1]
    WHERE [t1].[ROW_NUMBER] BETWEEN @p1 + 1 AND @p1 + @p2
    ) AS [t2]
ORDER BY [t2].[ROW_NUMBER]
-- @p0: Input UniqueIdentifier (Size = -1; Prec = 0; Scale = 0) [f311d7f3-3755-e411-940e-00155d0c0c4b]
-- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- @p2: Input Int (Size = -1; Prec = 0; Scale = 0) [51]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.17929

【问题讨论】:

  • 我认为您只是忘记将其分配回结果 --> results = results.Where( RecursiveHandleFilterExpression( query.Criteria ));

标签: c# sql recursion linq-to-sql predicatebuilder


【解决方案1】:

AndOr 方法不会改变表达式。 (这些对象是不可变的。)它们返回一个表示相关操作的 new 表达式。您忽略了代码中的返回值。

【讨论】:

    猜你喜欢
    • 2011-09-19
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 2016-08-14
    相关资源
    最近更新 更多