Home > Software design >  Is it necessary to check context.Inspections for null?
Is it necessary to check context.Inspections for null?

Time:07-01

I have an entity and context defined in Asp.Net Core Web API project with NRT (Nullable Reference Type) enabled as follows.

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

    [StringLength(20)]
    public string Status { get; set; } = string.Empty;
}

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> opts) : base(opts) { }

    public DbSet<Inspection> Inspections { get; set; } = null!;    
}

Visual Studio Community generates a controller and one of its endpoints is as follows.

[HttpGet]
public async Task<ActionResult<IEnumerable<Inspection>>> GetInspections()
{
    if (context.Inspections == null)
    {
        return NotFound();
    }
    return await _context.Inspections.ToListAsync();
}

However, many tutorials I read and watch don't check context.Inspections for null.

In addition, I have read that ToListAsync will return an empty list if no entry found.

Question: Is it necessary to do such a check? Does EF Core guarantee that the properties of type DbSet will never be null?

CodePudding user response:

No, these properties are initialized by the DbContext constructor.

The constructor uses an IDbSetInitialzer object to initialize all DbSet properties.

    ServiceProviderCache.Instance.GetOrAdd(options, providerRequired: false)
        .GetRequiredService<IDbSetInitializer>()
        .InitializeSets(this);

Using an IDbSetInitializer like this allows replacing it with mock initializers for test purposes.

The initializer will find all DbSets on the DbContext and initialize them:

/// <summary>
///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
///     the same compatibility standards as public APIs. It may be changed or removed without notice in
///     any release. You should only use it directly in your code with extreme caution and knowing that
///     doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual void InitializeSets(DbContext context)
{
    foreach (var setInfo in _setFinder.FindSets(context.GetType()).Where(p => p.Setter != null))
    {
        setInfo.Setter!.SetClrValue(
            context,
            ((IDbSetCache)context).GetOrAddSet(_setSource, setInfo.Type));
    }
}

Before EF Core 6, only entity sets specified through DbSet<> properties were cached, which resulted in performance gains over direct calls to Set<T>()

  • Related