Search code examples
c#.netentity-framework-coreef-code-first

Code-first foreign key references primary key in same table EF Core 7


I have this class with 2 fields, one serves as the primary key, and the other is a foreign key:

public partial class CCSSubCuenta
{
    [Key]
    [Required]
    [MaxLength(6)]
    [Column("SCTA_CLAVE", TypeName = "decimal(6)")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public decimal SctaClave { get; set; }

    [MaxLength(6)]
    [Column("SCTA_CLAVE_SCTA_MAESTRA", TypeName = "decimal(6)")]
    public decimal? SctaClaveSctaMaestra { get; set; }
}

I'm trying to use the [ForeignKey("SCTA_CLAVE")] for referencing the primary key, but it is not working when I deploy my migrations.

What is the correct way to define the foreign key via data annotations or Fluent API?


Solution

  • You can't use [ForeignKey] on a foreign key property.

    [ForeignKey] is to decorate a navigation property to indicate the foreign key column :

    public class File
    {
        public int Id { get; set; }
        public string Name { get; set; }
        [ForeignKey("FolderId")]
        public Folder? Folder { get; set; } // Navigation Property
    }
    

    Or the foreign key property :

    public class File
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int FolderId { get; set; } // Foreign Key Property
        [ForeignKey(nameof(FolderId))]
        public Folder? Folder { get; set; } // Navigation Property
    }
    

    It can also decorate a collection navigation property, but it's a other subject.


    In EF Core, it's the navigation property that define relation. But your model don't have navigation property.

    You need to define the relation with a navigation property like :

    public partial class CCSSubCuenta
    {
        [Key]
        ...
        public decimal SctaClave { get; set; }
    
        [MaxLength(6)]
        [Column("SCTA_CLAVE_SCTA_MAESTRA", TypeName = "decimal(6)")]
        public decimal? SctaClaveSctaMaestra { get; set; }
    
        [ForeignKey(nameof(SctaClaveSctaMaestra))]
        public CCSSubCuenta? SctaClaveSctaMaestraNav { get; set; }
    }
    

    If you don't want modify the model, you can add a shadow navigation property with the fluent syntax :

    public class CuentaContext : DbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<CCSSubCuenta>()
                .HasOne<CCSSubCuenta>()
                .WithMany()
                .HasForeignKey(c => c.SctaClaveSctaMaestra);
        }
    }