Efcore: Scaffolding and C# 8 nullable reference types

Created on 29 Apr 2019  路  5Comments  路  Source: dotnet/efcore

10347 makes EF Core recognize the new C# 8 nullable reference types (NRT), and treat them as [Required]. However, we still need to take care of scaffolding: the model we currently scaffold will not compile under projects with NRT enabled, as reference properties will be treated as non-nullable and the compiler will complain about them being uninitialized.

According to @bricelam it should be relatively easy to detect whether the project we're scaffolding into has turned on NRT or not. This would allow us to scaffold differently based on that setting.

Nullable database columns should obviously be scaffolded as nullable properties:

```c#
public string? SomeNullableProperty { get; set; }

For non-nullable columns, it seems that guidance is aligning to having non-nullable properties, forced-initialized to null as follows:

```c#
public string SomeNonNullableProperty { get; set; } = default!;

Note the null-forgiving bang operator which suppresses the warning. Alternatives for non-nullable properties include:

  • A single pragma suppressing the uninitialized warning for the entire file. This seems less obvious and more error-prone if the scaffolded model is later updated manually by the user.
  • Scaffold non-nullable properties backed by nullable fields, with a getter throwing InvalidOperationException if the value is null (i.e. if the property is accessed before initialization). While this is a better pattern than null-initialization (early and informative exception), it is also considerably more verbose and would probably put people off the NRT feature.
area-scaffolding punted-for-3.0 punted-for-5.0 type-enhancement

Most helpful comment

@grosch in 5.0, we scaffold #nullable disable into the source files we scaffold (this is #21190, and #23060 backports that to 3.1). This issue tracks having EF actually scaffold source code with proper nullability (i.e. with #nullable enable), based on whether you've turned the feature on in your project.

Scaffolding nullable code was scoped out of EF 5.0 because of prioritization/time constraints, especially considering that EF 5.0 doesn't support other aspects of nullability (e.g. EF's API itself isn't annotated). We plan to address all that for EF 6.0.

All 5 comments

I'll also add my two cents, that documentation for EF probably needs an update wrt to Nullable Reference Types. Right now, all tutorials and guides guide you to write your DbContext class as follows

public class MyDbContext : DbContext
{
    public MyDbContext(DbContextOptions options) : base(options) {}

    public DbSet<MyEntity> MyEntities { get; set; }
}

And this will produce a warning when compiling with NRTs.
I couldn't find an issue about tackling this in docs. Should I create one?

Triage: for 5.0, at least scaffold the disable.

Disabling nullability context has been done in #21190.

Why was this punted for version 5? It's painful when the entire project uses nullable, and then you have no idea with the model whether or not it's nullable.

@grosch in 5.0, we scaffold #nullable disable into the source files we scaffold (this is #21190, and #23060 backports that to 3.1). This issue tracks having EF actually scaffold source code with proper nullability (i.e. with #nullable enable), based on whether you've turned the feature on in your project.

Scaffolding nullable code was scoped out of EF 5.0 because of prioritization/time constraints, especially considering that EF 5.0 doesn't support other aspects of nullability (e.g. EF's API itself isn't annotated). We plan to address all that for EF 6.0.

Was this page helpful?
0 / 5 - 0 ratings