NRT is enabled.
I have the following models:
public class Blog
{
public int Id { get; set; }
public string Url { get; set; }
public Header Header { get; set; }
}
public class Header
{
public int Id { get; set; }
public string Title { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
According to docs, EF Core respects NRT and will use it to set columns to be nullable or not if NRT is enabled, which it is.
Now, I know that having Header
be non-nullable in a principal entity doesn't make sense, but EF Core is completely ignoring it. I can even create a Blog
without any Header
linked! A Header
will be set to NULL if I create a blog without a header.
It's also frustrating, even though it makes sense, that the compiler thinks it can't be NULL yet it is!
The migration code is:
migrationBuilder.CreateTable(
name: "Blogs",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Url = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Blogs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Headers",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Title = table.Column<string>(type: "TEXT", nullable: false),
BlogId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Headers", x => x.Id);
table.ForeignKey(
name: "FK_Headers_Blogs_BlogId",
column: x => x.BlogId,
principalTable: "Blogs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
How come EF Core is able to assign NULL
to a non-nullable property?
As you say, Blog
is the principal entity. Hence table Blog
doesn't have a HeaderId
, so the database allows Blogs without Headers. It even has no way to enforce Blogs to have Headers.
EF core has always followed the line of making validation a developer-responsibility and I think that's why they allow the entity model to do what the database allows. They're not going to validate it for you.
As for reading: you can configure Blog.Header
as auto-include.
Even then, you can still get a null
value in Blog.Header
, note that NRT is nothing but a compiler feature that issues warnings at compile-time where code may throw a NRE. It doesn't change anything on actual nullability of reference types. I.e. Blog.Header
can always be null. It's not a problem for C# with NRT enabled and EF chooses to not make it their problem.