1

I have a method which generates from my query.

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 used on Where extension from Linq dynamic like this:

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

My object that is used in the query is:

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

On argument for PrepereWhereClause are field of type string which are inside in ResponsibilityType, Employee and Supplier.

Query that is generated by PrepereWhereClause 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))

All is ok when ALL child elements are not null.

Problem is when some of them are null. I looking to this post on SO Dynamic Linq Core OrderBy Nullable Child Property and on issue on github and I try use but it doesn't work :(

I modified my query to this:

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

New query now 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 this error:

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

I try change && to AND but nothing change. What am I doing wrong?

I change query like @orxanmuv write but I still get an error.

Query for 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' incompatible with operand types 'Boolean' and 'String'

8
  • what is np() ? Commented Sep 29, 2021 at 7:00
  • 1
    @Cid it's native method inside Dynamic Linq. See this: github.com/zzzprojects/System.Linq.Dynamic.Core/issues/366 Commented Sep 29, 2021 at 7:06
  • 2
    I change image to code Commented Sep 29, 2021 at 7:10
  • and what's the return value of np? answering this question will give you a big hint about what is the origin of your problem Commented Sep 29, 2021 at 7:14
  • As i looking on linked post on SO You can see //Transforms => "a.b.c" to "(a != null ? (a.b != null ? a.b.c : null) : null)" Commented Sep 29, 2021 at 7:21

1 Answer 1

1

np method should be correct solution for Order By. For Where clause you have to check nulls in whole property path.

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 on whole path to the nested property. Regards

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.