【问题标题】:How to have foreign key and related navigation property with non-standard name如何拥有非标准名称的外键和相关导航属性
【发布时间】:2021-05-14 12:19:31
【问题描述】:

在 Entity Framework Core (v5.0.6) 中,我正在尝试创建一种关系,其中对象同时具有外键 id 字段和导航属性,两者都具有非标准名称,但是当我尝试构建迁移时,我收到一条错误消息Unable to determine the relationship represented by navigation 'Org.IntegrationAdmin' of type 'OrgUser'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'

我的代码是:

public class OrgUser
{
   public Guid Id { get; set; }
   public string Name { get; set; }
   public Guid OrgId { get; set; }
   public virtual Org? Org { get; set; }
}

public class Org
{
    [ForeignKey(nameof(OrgUser))]
    public Guid IntegrationAdminId { get; set; }

    [ForeignKey(nameof(IntegrationAdminId))]
    public virtual OrgUser? IntegrationAdmin { get; set; }
}

非标准名称的原因是 Org 类中实际上有几个外键/导航属性,因此不能选择使用标准命名。

我宁愿使用属性而不是流利的语法。

我想要同时拥有 id 和导航属性,因为有时会想要包含导航属性,但其他人只想要 id,这对于比较记录很有用,而无需进行 db join 的开销。

更新: 很抱歉浪费了人们的时间,但我犯了一个经典错误,无意中编辑了我的代码的重要部分????‍♂️????‍♂️????‍♂️ 我在 OrgUser 中添加了对 Org 的引用,这让 EF 感到困惑!

【问题讨论】:

  • 我在您的示例中没有看到非标准名称。它的方式应该在没有任何附加注释的情况下工作(包括两个[ForeignKey])。所以显然你还有其他东西没有在这里显示。而如果 EF 无法确定关系,最好学习并开始使用 fluent API/配置,因为有些东西(尤其是级联行为之类的关系)无法通过数据注释进行配置。
  • @Ivan IntegrationAdminId 是对 OrgUser 表的引用。该名称并不表示它所引用的表。
  • 不需要。重要的是类型,而不是名称。该名称仅适用于导航到 FK 道具关联,但一旦 FK 名称为导航道具名称 + Id,一切都很好(按照惯例)。可以看到约定here
  • @Ivan 感谢您的指点,您绝对正确;由于导航属性,它根本不需要 ForeignKey 属性。问题出在其他地方,正如我在上面的编辑和下面的回答中所解释的那样,我错过了问题中的一个重要细节,从而误导了所有人。

标签: c# entity-framework asp.net-core .net-core entity-framework-core


【解决方案1】:

试试这个

public class OrgUser
{
   [Key]
   public Guid Id { get; set; }
   public string Name { get; set; }

 [InverseProperty(nameof(Org.IntegrationAdmin))]
public virtual ICollection<Org> Orgs { get; set; }
}

public class Org
{
    [Key]
   public Guid Id { get; set; }
    
    public Guid? IntegrationAdminId { get; set; }

    [ForeignKey(nameof(IntegrationAdminId))]
    [InverseProperty("Orgs")]
    public virtual OrgUser IntegrationAdmin { get; set; }
}

或者你可以试试 dbcontext

modelBuilder.Entity<Org>(entity =>
            {
                entity.HasOne(d => d.IntegrationAdmin)
                   .WithMany(p => p.Orgs)
                   .HasForeignKey(d => d.IntegrationAdminId )
                   .OnDelete(DeleteBehavior.ClientSetNull);
                  
            });

【讨论】:

    【解决方案2】:

    我发现了问题,除了 Org 中的 OrgUser ref 之外,OrgUser 中还有一个我没有注意到的 Org ref。

    这让 EF 感到困惑,并导致一条错误消息指向错误的东西,让我大吃一惊。

    我删除了所有ForeignKey 属性,然后将以下内容添加到我的DbContext

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    
        modelBuilder.Entity<Org>(entity =>
        {
            entity.HasOne(o => o.IntegrationAdmin)
                  .WithMany();
        });
    
        modelBuilder.Entity<OrgUser>(entity =>
        {
            entity.HasOne(d => d.Org)
                  .WithMany();
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 2014-06-24
      相关资源
      最近更新 更多