Linq dynamic query problem - operator '&&' is incompatible with operand types 'String' and 'Boolean'


newer

I have a method which generally forms my qeury. It looks like this:

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

This query is for the Where extension from Linq Dynamic as follows:

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

What is the query inside my object:

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

The parameters of PrepereWhereClause are fields of type string, which are in ResponsibilityType, Employee, and Supplier.

The query PrepereWhereClause produces is:

(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))

Everything is ok when all child elements are not empty. The problem is when some of them are empty. I was looking forward to this post about SO Dynamic Linq Core OrderBy Nullable Child Property and about the issue on github , I tried to use but it doesn't work :( I modified my query for someone:

     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;
    }

The new query is:

((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)))

but I always get the error:

Operator '&&' incompatible with operand types 'String' and 'Boolean'

I tried changing && to AND but nothing changed. What am I doing wrong?

I changed the query like @orxanmuv write but I still get the error:

Query it:

(((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)))

Error: {"Operator 'or' is incompatible with operand types 'Boolean' and 'String'"}

mash up

The np method should be the correct solution for Order By. For the Where clause, you must check the entire property path for null values.

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})";
}

It will generate null checks for the entire path of nested properties. greeting

Related


Operand type is incompatible with operator

Noppadet i get error Operand type is incompatible with operator Click OK in the header when trying to compare two "real" data types. Can anyone help me with what problem? public void clicked() { real localAnnualUsage = itemSetup_DS.AnnualUsage();

Operand type is incompatible with operator

Noppadet i get error Operand type is incompatible with operator Click OK in the header when trying to compare two "real" data types. Can anyone help me with what problem? public void clicked() { real localAnnualUsage = itemSetup_DS.AnnualUsage();

Operand Types of Binary AND Operator

username Which type of operator uses the logical AND operator (&)? I need to input AND shorts aand a "number" mfrom 1 to 16 and get another short b. That primitive type must be m? example: ? m = ...; //with 1 <= m <= 16 short a = 2; short b = a & m; The examp

Operand Types of Binary AND Operator

username Which type of operator uses the logical AND operator (&)? I need to input AND shorts aand a "number" mfrom 1 to 16 and get another short b. That primitive type must be m? example: ? m = ...; //with 1 <= m <= 16 short a = 2; short b = a & m; The examp