简体   繁体   中英

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

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

how about simplifying your code into something like

public IEnumerable<Plan> GetPlans(int year)
{
    return _context.Plans
        .Where(e => e.Excercise.Year == year)
        .ToList();
}

To avoid this issue, make sure that you are not evaluating on null object.

var exercice = await _repositoryExercice.FirstOrDefaultAsync(i => i.IsCurrent);
var depenses = _repositoryDepense.GetAll()
                .Where( e => e.ExerciceId.Equals(exercice.Id))
                .WhereIf(AbpSession.TenantId.HasValue, m => m.TenantId.Value.Equals(AbpSession.TenantId.Value))
                .ToList();

The issue was causing by this line .Where( e => e.ExerciceId.Equals(exercice.Id)) because the variable exercice is null.

Best practice, I replaced that line by this :

...
.WhereIf(exercice != null, e => e.ExerciceId.Equals(exercice.Id))
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM