Search code examples
c#entity-frameworkc#-8.0nullable-reference-types

C# 8 Non-Null Reference Types for Database models with foreign key


I'am trying to implement non-null-reference-types in my project https://dev.to/integerman/safer-code-with-c-8-non-null-reference-types-4f2c. I like it, but have a question regarding database models and constraints.

Is there a way to say that value X is never NULL because it's not nullable in the database?

For example:

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

      public string Name { get; set; } = "No name set";

      public IEnumerable<Dog> Dogs { get; set; } = new List<Dog>();
}

Person.Name is nullable=false in the database. Is there a way I can say that this property is never null? Now I have to set a default value.

public class Dog
{
    public int Id { get; set; }
   
    public string Name { get; set; } = "Noname";

    public int PersonId {get; set; }

    public Person Person { get; set; }
}

Here I wonder the same about Person from Dog. This is a foreign key constraint in the database, A Dog can't exist without an Person(owner). Is there a way to say that; I know that this value is never null trust me or something like that ?

[Update]

Is there a way to say that value X is never NULL because it's not nullable in the database?

Yes, see Pavel Anikhouski answer

Should you do it:

No, see TomTom s answer

The best solution I think is @canton7 last comment. He links to this; https://learn.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types#non-nullable-properties-and-initialization

Another reason:

public IEnumerable<Dog> Dogs { get; set; } = new List<Dog>();

If you are trying to get a Person like this:

var person = _dbcontext.persons.Single(x => x.Name == "John").ToList(); 
Console.log($"John has {person.Dogs.Count} dogs")

This will output 0 everytime, because we forgot to .Include(x => x.dogs). So it's wrong.


Solution

  • You can use null forgiving operator ! for that

    public Person Person { get; set; } = default!;
    

    As it pointed in comments, you should carefully use it, since it works with any type (value or reference one) and you can use null! as well