【问题标题】:EF Core self referencing not working if there are 2 foreign keys to self (Code first)如果自身有 2 个外键,则 EF Core 自引用不起作用(代码优先)
【发布时间】:2017-10-19 10:26:29
【问题描述】:

如果我定义(首先在代码中)一个导航属性到 self 它可以工作(创建外键),但如果我定义 2 它不起作用。
如何创建 2 个外键self? 按照惯例,它们应该基于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。同样,在向 self (ParentId, RootId) 引用 2 个属性时不会创建外键。

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

【问题讨论】:

  • 错误信息是什么?
  • 没有错误,只是列没有定义为外键。

标签: entity-framework entity-framework-core


【解决方案1】:

我更喜欢这些东西的流畅代码:

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; }
}

【讨论】:

  • 我更喜欢注释。对我来说看起来更具可读性。而且您的带有注释的想法不起作用(看起来像错误)。流畅的代码工作。
  • 不使用注释对我来说似乎是错误,所以我在GitHub 上发布问题。
猜你喜欢
  • 2018-10-28
  • 2013-09-04
  • 2016-10-16
  • 2018-02-13
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
相关资源
最近更新 更多