Jak używać zerowych typów referencyjnych C # 8.0 z modelami Entity Framework Core?

16

Włączam typy referencyjne Nullable C # 8.0 w projekcie .NET Core 3.0. Projekt korzysta z Entity Framework Core 3.0, aby uzyskać dostęp do bazy danych.

Poniżej przedstawiono model danych, którego tytuł nie powinien mieć wartości null.

public class Vehicle
{
    public int Id { get; private set; } 

    public string Title { get; private set; }

    // Entity Framework Core is instructed to bind to the private _drivers field in a configuration builder
    private readonly List<Driver> _drivers = new List<Driver>();
    public IReadOnlyCollection<Driver> Drivers => _drivers.AsReadOnly();

    private Vehicle() 
    {
    }

    public Vehicle(string title) 
    {
        this.Title = title;
    }

    public void AddDriver(string name)
    {
         this._drivers.Add(new Driver(name));
    }
 }

// A foreign column is defined in a configuration builder
public class Driver
{
    public int Id { get; private set; } 

    public string Name { get; private set; }

    private Driver() 
    {
    }

    public Driver(string name) 
    {
        this.Name = name;
    }
 }

Własny kod ma używać publickonstruktorów tylko wtedy, gdy privatekonstruktory są tam po to, aby umożliwić Entity Framework Core i (potencjalnie również) serializacji powiązać wartości z bazy danych z tymi klasami / modelami. Konstruktor publiczny może mieć inną strukturę, listę i typy argumentów niż właściwości, które ma model (na przykład może również zawierać argumenty dla pierwszego wymaganego dziecka, niektóre argumenty mogą być opcjonalne itp.).

Jednak kompilator generuje CS8618 Non-nullable field is uninitialized. Consider declaring as nullable.na privatekonstruktorach.

Jestem w stanie wyłączyć CS8616 dla privatekonstruktorów, #pragma warning disable CS8618ale nie uważam tego za dobry pomysł.

Jak w tym scenariuszu należy używać typów referencyjnych dopuszczających wartości zerowe C # 8.0? A może mój model jest fałszywy lub narusza najlepsze praktyki - jak to zrobić poprawnie?

Niestety nie znalazłem odpowiednich dokumentów ani wskazówek.

alik
źródło

Odpowiedzi:

6

Nie ma właściwego sposobu obsługi właściwości nawigacyjnych, które nie zawierają wartości zerowych.

  1. Dokumentacja sugeruje dwa sposoby i oba nie są bezpieczne dla typu. Użyj pola zaplecza i wyrzuć InvalidOperationException. Nie jest jasne, w jaki sposób różni się od nic nie robienia i ma wyjątek NullReferenceException
  2. Pomiń to operatorem wybaczającym zero

Oficjalny link do dokumentacji: https://docs.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types#non-nullable-properties-and-initialization

Michaił Żurawlew
źródło
2

Z MS Docs dla typów jednostek z konstruktorami

Gdy EF Core tworzy instancje tego typu, na przykład dla wyników zapytania, najpierw wywoła domyślnego konstruktora bez parametrów, a następnie ustawi każdą właściwość na wartość z bazy danych. Jeśli jednak EF Core znajdzie sparametryzowany konstruktor z nazwami i typami parametrów zgodnymi z właściwościami odwzorowanymi, wówczas wywoła sparametryzowany konstruktor z wartościami dla tych właściwości i nie ustawi jawnie każdej właściwości.

Być może warto utworzyć prywatny ctor z parametrem potrzebnym dla tych właściwości i sprawdzić, czy Framework zadzwoni i zadziała?

Wyłączenie ostrzeżeń nie jest dobrym pomysłem, chyba że masz pełną 100% pewność, że można je wyłączyć.

kobiassvilli
źródło