Linq 动态查询问题 - 运算符“&&”与操作数类型 'String' 和 'Boolean' 不兼容
Linq Dynamic Query Issue - Operator '&&' incompatible with operand types 'String' and 'Boolean'
我有一个从我的查询生成的方法。
看起来像这样:
private static string PrepareWhereClause(string[] columns)
{
var query = $"({string.Join(" OR ", columns?.Select(c => $"{c} != null AND {c}.ToLower().Contains(@0)"))})";
return query;
}
此查询用于 Where
来自 Linq dynamic 的扩展,如下所示:
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
的参数是 ResponsibilityType
、Employee
和 Supplier
.
中的字符串类型的字段
由 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 上查看此 post 并在 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)))
但我总是得到这个错误:
Operator '&&' incompatible with operand types 'String' and 'Boolean'
我尝试将 && 更改为 AND 但没有任何变化。我做错了什么?
我像@orxanmuv write 一样更改了查询,但我仍然收到错误。
查询:
(((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)))
错误:
Operator 'or' incompatible with operand types 'Boolean' and 'String'
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})";
}
它将对嵌套 属性 的整个路径生成空检查。
此致
我有一个从我的查询生成的方法。
看起来像这样:
private static string PrepareWhereClause(string[] columns)
{
var query = $"({string.Join(" OR ", columns?.Select(c => $"{c} != null AND {c}.ToLower().Contains(@0)"))})";
return query;
}
此查询用于 Where
来自 Linq dynamic 的扩展,如下所示:
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
的参数是 ResponsibilityType
、Employee
和 Supplier
.
由 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
我将查询修改为:
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)))
但我总是得到这个错误:
Operator '&&' incompatible with operand types 'String' and 'Boolean'
我尝试将 && 更改为 AND 但没有任何变化。我做错了什么?
我像@orxanmuv write 一样更改了查询,但我仍然收到错误。
查询:
(((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)))
错误:
Operator 'or' incompatible with operand types 'Boolean' and 'String'
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})";
}
它将对嵌套 属性 的整个路径生成空检查。 此致