The documentation for Include is:
public static System.Linq.IQueryable<T> Include<T,TProperty> (this System.Linq.IQueryable<T> source, System.Linq.Expressions.Expression<Func<T,TProperty>> path) where T : class;
But for the line of code:
numCountySignups = context.Counties.Include(c => c.Events).ThenInclude(e => e.Signups).First(c => c.Id == county.Id).Events.Sum(ee => ee.Signups.Count);
I get the warning:
Severity Code Description Project File Line Suppression State
Warning CS8620 Argument of type 'IIncludableQueryable<County, ICollection<Event>?>' cannot be used for parameter 'source' of type 'IIncludableQueryable<County, IEnumerable<Event>>' in 'IIncludableQueryable<County, ICollection<Signup>?> EntityFrameworkQueryableExtensions.ThenInclude<County, Event, ICollection<Signup>?>(IIncludableQueryable<County, IEnumerable<Event>> source, Expression<Func<Event, ICollection<Signup>?>> navigationPropertyPath)' due to differences in the nullability of reference types. IntegrationTests C:\git\LouisHowe\IntegrationTests\repository\TestCounty.cs 203 Active
which goes away if I add a ! as follows:
numCountySignups = context.Counties.Include(c => c.Events)!.ThenInclude(e => e.Signups).First(c => c.Id == county.Id).Events.Sum(ee => ee.Signups.Count);
As the declaration of Include() shows it to be non-nullable, why do I get this warning?
The documentation reference you included was from EF 5 (.Net Framework) rather than EF Core. NRTs can be problematic in EF with compiler warnings, especially with EF Core prior to 6.0. If you are running EF Core 5 then you should look to upgrade to EF Core 6 or 7.
One detail is to ensure that all collection navigation properties are initialized in your entities:
public class County
{
// ...
public virtual ICollection<Event> Events { get; private set; } = new List<Event>();
}
Lastly, the example query you provided is a particularly inefficient way to get the Sum:
numCountySignups = context.Counties
.Include(c => c.Events)
.ThenInclude(e => e.Signups)
.First(c => c.Id == county.Id)
.Events.Sum(ee => ee.Signups.Count);
This loads all events and signups for the given county into memory just to get a sum of the signup count. Instead:
numCountySignups = context.Counties
.Where(c => c.Id == county.Id)
.Select(c => c.Events.Sum(ee => ee.Signups.Count))
.First();
This would build and execute an SQL statement against the database to retrieve just that sum.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With