GrizzlyEnglish
GrizzlyEnglish

Reputation: 131

Moq with LINQ to entity projection

I am trying to integrate MOQ into my project that utilizes linq to entities - and for the most part it works as expected. The issue I am running into is when I am projecting to an anonymous object that has nullable properties that the "SQLizer" can handle but MOQ throws an exception.

For example:

public class Person {
    public int Id {get;set;}
    public virtual void Car Car {get; set;}
}

public class Car {
   public int Id {get;set;}
}

public class Context {
   public DbSet<Car> Cars {get;set;}
   public DbSet<Person> People {get;set;}
}

// Just to show we have a person in the db without a car
context.People.Add(new Person{
   Id = 1,
});

// This throws an exception on MOQ, but works in SQL
context.People.Select(person => new {
   personId = person.Id,
   carId = (int?)person.Car.Id
});

I tried to only highlight the issue I was having, maybe not the best structure of data. Thoughts on how to handle this? The easiest is checking for null values prior to the projection, but I feel like there is probably a better alternative.

Upvotes: 1

Views: 86

Answers (1)

Arsen Khachaturyan
Arsen Khachaturyan

Reputation: 8320

When you are adding a new Person using your context, it seems you are skipping to add the Car instance and trying to access it later:

context.People.Select(person => new {
   personId = person.Id,
   carId = (int?)person.Car.Id // above you instantiated a Person without a Car instance
});

What is happening here is that during the projection of the new element, the Select statement is trying to access the Car instance, which simply doesn't exist.

However, if you want to have Person instances which will not contain Car change your code to match one of two approaches:

1st option (use null-coalescing and null-conditional operator)

context.People.Select(person => new {
   personId = person.Id,
   carId = person.Car?.Id ?? 0 // 0 is the default value in case if Person doesn't have Car
});

2nd option use filtering

context.People.Where(p => p.Car != null).Select(person => new {
   personId = person.Id,
   carId = person.Car.Id
});

Upvotes: 1

Related Questions