Home > Enterprise >  How can I specify my relationship as optional in EF Core 6
How can I specify my relationship as optional in EF Core 6

Time:10-17

I have a class Personnage which should own multiple Histoires and should have one Default Histoire.

Here are the classes :

public class Personnage
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Nom { get; set; }
    public int? DefaultHistoireId { get; set; }
    public virtual Histoire? DefaultHistoire { get; set; }
    public List<Histoire> Histoires { get; set; } = new List<Histoire>();

}
public class Histoire
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Nom { get; set; }
    public DateTime DateDebut { get; set; }
    public DateTime? DateFin { get; set; } = null;
    public List<Dialogue> Dialogues { get; set; } = new List<Dialogue>();

    public int PersonnageId { get; set; }
    public virtual Personnage Personnage { get; set; }

    public int? DefaultForPersonnageId { get; set; } = null;
    public virtual Personnage? DefaultForPersonnage { get; set; } = null;
}

I have to create the Personnage first, so the relationship between Personnage.DefaultHistoire and Histoire should be optional.

I tried to make the properties Personnage.DefaultHistoire and Personnage.DefaultHistoireId as nullable "?" in my code, and added this to my DbContext.OnModelCreating :

modelBuilder
            .Entity<Personnage>()
            .HasOne(x => x.DefaultHistoire)
            .WithOne(x => x.DefaultForPersonnage)
            .IsRequired(false)
            .HasForeignKey<Histoire>(x => x.DefaultForPersonnageId)
            .HasPrincipalKey<Personnage>(x => x.DefaultHistoireId)
            .OnDelete(DeleteBehavior.Cascade);

But in the Migration generated code, it still make the property as nullable: false :

migrationBuilder.CreateTable(
            name: "Personnages",
            schema: "dbo",
            columns: table => new
            {
                Id = table.Column<int>(type: "integer", nullable: false)
                    .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
                Nom = table.Column<string>(type: "text", nullable: false),
                DefaultHistoireId = table.Column<int>(type: "integer", nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Personnages", x => x.Id);
                table.UniqueConstraint("AK_Personnages_DefaultHistoireId", x => x.DefaultHistoireId);
            });

How can I mark this relationship as optional ?

CodePudding user response:

.HasPrincipalKey<Personnage>(x => x.DefaultHistoireId);, then Personnage.DefaultHistoireId will act like a primary key, unique value and not nullable.

Maybe Histoire.DefaultForPersonnageId and Histoire.DefaultForPersonnage can be removed and Personnage.DefaultHistoireId reference directly Histoire.Id :

modelBuilder
    .Entity<Personnage>()
    .HasOne(x => x.DefaultHistoire)
    .WithOne()
    .HasForeignKey<Personnage>(x => x.DefaultHistoireId)
    .OnDelete(DeleteBehavior.Cascade);

public class Histoire
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Nom { get; set; }
    public DateTime DateDebut { get; set; }
    public DateTime? DateFin { get; set; } = null;
    public List<Dialogue> Dialogues { get; set; } = new List<Dialogue>();

    public int PersonnageId { get; set; }
    public virtual Personnage Personnage { get; set; }

    //public int? DefaultForPersonnageId { get; set; } = null;
    //public virtual Personnage? DefaultForPersonnage { get; set; } = null;
}
  • Related