【问题标题】:Linq Dynamic Query Issue - Operator '&&' incompatible with operand types 'String' and 'Boolean'Linq 动态查询问题 - 运算符“&&”与操作数类型“字符串”和“布尔”不兼容
【发布时间】:2021-11-21 02:01:59
【问题描述】:

我有一个从我的查询中生成的方法。

看起来像这样:

private static string PrepareWhereClause(string[] columns)
{
    var query = $"({string.Join(" OR ", columns?.Select(c => $"{c} != null AND {c}.ToLower().Contains(@0)"))})";
    return query;
}

此查询用于来自 Linq 动态的 Where 扩展,如下所示:

public static IQueryable<T> Search<T>(this IQueryable<T> queryable, string phrase, params string[] columns) =>
        queryable?.Where(PrepareWhereClause(columns), phrase.ToLower());

我在查询中使用的对象是:

public class ResponsibilitiesWebDto
{
    public Guid Id { get; set; }
    public DictionaryBaseDto ResponsibilityType { get; set; }
    public UserForDetailedDto Employee { get; set; }
    public SupplierForDetailedDto Supplier { get; set; }
}

PrepereWhereClause 的参数是字符串类型的字段,位于 ResponsibilityTypeEmployeeSupplier 中。

PrepereWhereClause 生成的查询是:

(ResponsibilityType.Name != null AND ResponsibilityType.Name.ToLower().Contains(@0) OR Employee.EmployeeId != null AND Employee.EmployeeId.ToLower().Contains(@0) OR Employee.Name != null AND Employee.Name.ToLower().Contains(@0) OR Employee.LastName != null AND Employee.LastName.ToLower().Contains(@0) OR Supplier.AccountNum != null AND Supplier.AccountNum.ToLower().Contains(@0) OR Supplier.Name != null AND Supplier.Name.ToLower().Contains(@0))

当所有子元素都不为空时,一切正常。

问题是其中一些为空。我在 SO Dynamic Linq Core OrderBy Nullable Child Property 和 github 上查看这篇文章,我尝试使用,但它不起作用:(

我将查询修改为:

private static string PrepareWhereClause(string[] columns)
{
    var query = $"({string.Join(" OR ", columns?.Select(c => $"{c} != null AND {c}.ToLower().Contains(@0)"))})";
    var query1 = $"({string.Join(" OR ", columns?.Select(c => "((" + ConvertToNullableNested(c) + $") AND {c}.ToLower().Contains(@0))"))})";
    var query2 = $"({string.Join(" OR ", columns?.Select(c => $"np({c} != null AND {c}.ToLower().Contains(@0)"))})";
    var query3 = $"({string.Join(" OR ", columns?.Select(c => $"(np({c}) AND {c}.ToLower().Contains(@0))"))})";
    var query4 = $"({string.Join(" OR ", columns?.Select(c => $"(np({c}) && {c}.ToLower().Contains(@0))"))})";

    return query4;
}

现在的新查询是:

((np(ResponsibilityType.Name) && ResponsibilityType.Name.ToLower().Contains(@0)) OR (np(Employee.EmployeeId) && Employee.EmployeeId.ToLower().Contains(@0)) OR (np(Employee.Name) && Employee.Name.ToLower().Contains(@0)) OR (np(Employee.LastName) && Employee.LastName.ToLower().Contains(@0)) OR (np(Supplier.AccountNum) && Supplier.AccountNum.ToLower().Contains(@0)) OR (np(Supplier.Name) && Supplier.Name.ToLower().Contains(@0)))

但我总是得到这个错误:

运算符 '&&' 与操作数类型 'String' 和 'Boolean' 不兼容

我尝试将 && 更改为 AND,但没有任何改变。我做错了什么?

我更改了@orxanmuv 之类的查询,但我仍然收到错误。

查询它:

(((np(ResponsibilityType.Name) == null or np(ResponsibilityType.Name)) AND ResponsibilityType.Name.ToLower().Contains(@0)) OR ((np(Employee.EmployeeId) == null or np(Employee.EmployeeId)) AND Employee.EmployeeId.ToLower().Contains(@0)) OR ((np(Employee.Name) == null or np(Employee.Name)) AND Employee.Name.ToLower().Contains(@0)) OR ((np(Employee.LastName) == null or np(Employee.LastName)) AND Employee.LastName.ToLower().Contains(@0)) OR ((np(Supplier.AccountNum) == null or np(Supplier.AccountNum)) AND Supplier.AccountNum.ToLower().Contains(@0)) OR ((np(Supplier.Name) == null or np(Supplier.Name)) AND Supplier.Name.ToLower().Contains(@0)))

错误:

运算符“或”与操作数类型“布尔”和“字符串”不兼容

【问题讨论】:

  • np() 是什么?
  • @Cid 它是 Dynamic Linq 中的本机方法。看到这个:github.com/zzzprojects/System.Linq.Dynamic.Core/issues/366
  • 我把图片改成代码
  • np 的返回值是多少?回答这个问题会给你一个关于问题根源的重要提示
  • 当我查看 SO 上的链接帖子时,您可以看到 //Transforms => "abc" 到 "(a != null ? (ab != null ?abc : null) : null)"

标签: c# linq asp.net-core dynamic-linq


【解决方案1】:

np 方法应该是 Order By 的正确解决方案。对于 Where 子句,您必须检查整个属性路径中的空值。

private static string PrepareWhereClause(string[] columns) => $"({string.Join(" OR ", columns?.Select(c => BuildLinqExpressionForNestedObject($"{c} != null AND {c}.ToLower().Contains(@0)", c)))})";

private static string BuildLinqExpressionForNestedObject(string propertyExpression, string propertyName)
{
    var propertyPath = propertyName.Split(".");
    if (propertyPath.Length > 1)
    {
        List<string> nullChecks = new List<string>();
        for (int i = 0; i < propertyPath.Length - 1; i++)
        {
            var nullCheck = $"{string.Join(".", propertyPath.Take(i + 1))} != null";
            nullChecks.Add(nullCheck);
        }
        return $"({string.Join(" AND ", nullChecks)} AND {propertyExpression})";
    }
    return $"({propertyExpression})";
}

它将对嵌套属性的整个路径生成空检查。 问候

【讨论】:

    猜你喜欢
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 2014-11-24
    相关资源
    最近更新 更多