Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where Predicates in LINQ

Tags:

c#

linq

How can I specify conditions in Where predicates in LINQ without getting null reference exceptions. For instance, if q is an IQueryable how can I do like:

Expression<Func<ProductEntity,bool>> predicate = p => !search.CategoryId.HasValue || (search.CategoryId.HasValue && search.CategoryId == p.CategoryId);

var q2 = q.Where(predicate);

Here search is an object that holds possible search conditions that may or may not be set like search.CategoryId might not be set but if it is I want to get the products that are set by that condition.

When I do this I get null reference exceptions.

like image 440
JustAProgrammer Avatar asked Feb 21 '10 09:02

JustAProgrammer


2 Answers

You can use the null-coalescing operator ?? to replace a possible null value with a default value. The following sets tries to match the search.Category if it exists or simply creates an "always true" expression. This will be optimized by any good Linq query provider (e.g. LinqToSql).

Expression<Func<ProductEntity,bool>> predicate = p => (search.CategoryId ?? p.CategoryId) == p.CategoryId);

var q2 = q.Where(predicate);

Another possibility would be to dynamically compose a query predicate using PredicateBuilder. That's the way I do it for searches with a similar pattern as you use:

var predicate = PredicateBuilder.True<Order>();

if (search.OrderId))
{
   predicate = predicate.And(a => SqlMethods.Like(a.OrderID, search.OderID);  
}
// ...
var results = q.Where(predicate);
like image 74
Johannes Rudolph Avatar answered Sep 28 '22 03:09

Johannes Rudolph


Let's dissect the line:

Expression<Func<ProductEntity,bool> predicate = p => !search.CategoryId.HasValue
       || (search.CategoryId.HasValue && search.CategoryId == p.CategoryId)
var q2 = q.Where(predicate);

So how many ways can we get null problems?

  • search (your "captured" variable) could be null
  • p could be null, meaning there is a null in the list
  • you've handled the case of search.CategoryId being null (Nullable<T>)
  • but maybe p.CategoryId (the category on a record in the list) is null (Nullable<T>) - however, I'm not sure that this would cause a NullReferenceException
  • q (the list / source) could be null

So: out of 5 options you've eliminated 1; look at the other 4? There is also the definite possibility that the issue is caused by something invisible not shown in the code; for example the get could be:

public int? CategoryId {
    get {return innerObject.CategoryId;}
}

and innerObject could be null; if you eliminate the other 4 (pretty easy to do), look at at this one as a last resort.

like image 37
Marc Gravell Avatar answered Sep 28 '22 04:09

Marc Gravell