Search code examples
.net-coreentity-framework-coreef-code-firstentity-framework-migrations

Entity Framework Core 5.0 Reference Navigation RequiredAttribute + Migration not working


We've just recently upgraded an ASP.NET Core project to 5.0 with all the Entity Framework (nuget) upgrades available - bringing it all to the latest 5.0 release.

When creating a new migration, it appears a reference navigation property attributed with [Required] no longer causes the migration to create the column as NOT NULL.

Our code (note the Template reference navigation property):

/// <summary>
/// A document is a completed template
/// </summary>
public class Document
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public int? Id { get; set; }
    [Required]
    public string Name { get; set; }

    public int CompanyRecId { get; set; }
    public int AgreementRecId { get; set; }
    /// <summary>
    /// A HistoryId is common to all documents copied from an original document.
    /// Thus;
    /// - A document is created via a template
    /// - A second document is created by the original document.
    /// - The two documents are linked by the same GroupId.
    /// </summary>
    [Required]
    public Guid HistoryId { get; set; }
    [Required]
    public string Creator { get; set; }
    [Required]
    public DateTime Created { get; set; }
    [Required]
    public virtual Template Template { get; set; }

...constructors, methods follow

When creating a migration (Add-Migration Update17 for instance), the following (Up) code is generated:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_Documents_Templates_TemplateId",
            table: "Documents");

        migrationBuilder.AlterColumn<int>(
            name: "TemplateId",
            table: "Documents",
            type: "int",
            nullable: true,
            oldClrType: typeof(int),
            oldType: "int");

        migrationBuilder.AddForeignKey(
            name: "FK_Documents_Templates_TemplateId",
            table: "Documents",
            column: "TemplateId",
            principalTable: "Templates",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }

The TemplateId column is being changed from the previous nullable: false to nullable: true - my question is why?

I have read the breaking changes documentation here and the relationships documentation here which seems to indicate that the functionality has changed, but looks like not in this specific scenario? When adding a TemplateId property (int?) with the RequiredAttribute on it - the migration works as expected and nothing changes on the TemplateId column.

I seem to be missing something or not understanding the documentation clearly - any help would be appreciated!


Solution

  • To resolve the issue, I added a property on the Template class -

    public virtual List<Document> Documents { get; set ; }
    

    This seemed to give the EF Tools what it needed to detect the RequiredAttribute and correctly build the migration.