如果自己有2个外键,则EF Core自引用不起作用(代码优先)

时间:2017-10-19 10:26:30

标签: entity-framework entity-framework-core

如果我(在代码中首先)将一个导航属性定义为self(它创建了外键),但是如果我定义了2则它不起作用。
如何为自己创建2个外键?根据约定documentation创建它们。

例如,这可以工作(创建外键):

public class DbPart 
{
    [Key]
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [ForeignKey("Source")]
    public int? SourceId { get; set; }
    public DbPart Source { get; set; }

    [InverseProperty("Source")]
    public List<DbPart> SourceParts { get; set; }
}

这是这样的:

public class DbPart 
{
    [Key]
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [ForeignKey("SourceFake")]
    public int? SourceFakeId { get; set; }
    public DbPart SourceFake { get; set; }

    [InverseProperty("SourceFake")]
    public List<DbPart> SourceFakeParts { get; set; }
}

但不是这样:

public class DbPart 
{
    [Key]
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [ForeignKey("Source")]
    public int? SourceId { get; set; }
    public DbPart Source { get; set; }


    [ForeignKey("SourceFake")]
    public int? SourceFakeId { get; set; }
    public DbPart SourceFake { get; set; }

    [InverseProperty("SourceFake")]
    public List<DbPart> SourceFakeParts { get; set; }

    [InverseProperty("Source")]
    public List<DbPart> SourceParts { get; set; }
}

我还有另一个例子,我在数据库中编写树结构,但只写了ParentId,我也写了RootId。同样,在将2个属性引用到self(ParentId,RootId)时,不会创建外键。

编辑:
由于this错误,它无法正常工作。简单的解决方案是从Id属性中删除[Key]或在Steve Greene的答案中使用流畅的解决方案。另请检查here

1 个答案:

答案 0 :(得分:4)

我更喜欢这个东西的流利代码:

modelBuilder.Entity<DbPart>()
    .HasOne(p => p.Source)
    .WithMany(p => p.SourceParts)
    .HasForeignKey(p => p.SourceId);

modelBuilder.Entity<DbPart>()
    .HasOne(p => p.SourceFake)
    .WithMany(p => p.SourceFakeParts)
    .HasForeignKey(p => p.SourceFakeId);

但是如果你想要注释,试试这个:

public class DbPart 
{
    public int Id { get; set; }   // Key & Indentity by convention

    public int? SourceId { get; set; }  // FK by convention
    [InverseProperty("SourceParts")]
    public DbPart Source { get; set; }

    public int? SourceFakeId { get; set; } // FK by convention
    [InverseProperty("SourceFakeParts")]
    public DbPart SourceFake { get; set; }

    [InverseProperty("SourceFake")]
    public List<DbPart> SourceFakeParts { get; set; }

    [InverseProperty("Source")]
    public List<DbPart> SourceParts { get; set; }
}