Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null reference exception being thrown in EF LINQ query if-clause

I couldn't find the exact words to explain what's happening, so if this is a duplicated question, I apologize.

I tried to do a quite simple AND condition if-clause inside a LINQ Query, in order to check if an object is null and then verify if its property is equal or not the column I wanted to compare.

The code:

public IEnumerable<Plan> GetPlans(Plan plan)
    {
        return _context.Plans.Where(e =>
            e.Situation == plan.Situation &&
            e.Notes.Contains(plan.Notes) &&
            (plan.Excercise != null && plan.Exercise.Year > 0 ? e.Exercise.Year == plan.Exercise.Year: true)).ToList();
    }

I've already done this kind of check a dozen times before in .NET 4.5, without having any kind of issue.

But now, in the first .NET Core 2.0 project I'm working on, I had the following error:

An exception was thrown while attempting to evaluate a LINQ query parameter expression. To show additional information call EnableSensitiveDataLogging() when overriding DbContext.OnConfiguring.

The inner exception is clearer: NULL REFERENCE EXCEPTION.

After some tests, I found out that the error happens when plan.Exercise comes null, even if I try to avoid the exception by checking at first if it's null or not.

If I try to do the same check directly in Immediate Window, it returns "false", as it should be.

Am I missing something here? It could be an EF bug? Any particular reason why this works in .NET 4.5, for example, and not in .NET Core 2.0?

Thanks in advance.

UPDATE

Ivan's solution did the job:

Rewrite ? : constructs with equivalent ||

plan.Excercise == null || plan.Exercise.Year <= 0 || e.Excercise.Year == plan.Exercise.Year
like image 588
thiagoprzy Avatar asked Jan 08 '18 19:01

thiagoprzy


1 Answers

It sounds like this might be a bug in EF Core (but I don't know this for sure).

One thing you might try is to fail fast if the base requirements of plan are not met, and more importantly, instead of using the ternary operator, use the traditional comparison operators along with parenthesis:

public IEnumerable<Plan> GetPlans(Plan plan)
{
    if (plan == null) return new List<Plan>();

    return _context.Plans
        .Where(e =>
            e.Situation == plan.Situation &&
            e.Notes.Contains(plan.Notes) &&
            (plan.Exercise == null || 
            plan.Exercise.Year <= 0 || 
            e.Excercise.Year == plan.Exercise.Year))
        .ToList();
}
like image 127
Rufus L Avatar answered Sep 22 '22 19:09

Rufus L