“propertyName”不能作为“typeName”实体类型上的属性使用,因为它被配置为导航属性。

34

我有一个实体user,其中包含以下内容:

public class User
{
    [Key, Required]
    public int Id { get; set; }
    public int GenderId { get; set; }
    public virtual Gender Gender { get; set; }
}

性别方面:

public class Gender
{
    [Key, Required]
    public int Id { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

然后,在我的DbContext内部,我有:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>(user =>
    {
        user
        .HasOne(x => x.Gender)
        .WithMany(x => x.Users)
        .HasForeignKey(x => x.GenderId);
    }

    user.HasIndex(x => x.Gender);
}
当我运行dotnet ef add migration User时,出现错误:

'Gender'不能用作实体类型'User'上的属性,因为它被配置为导航。


1
错误不可能来自所显示的模型和配置。你的真实代码中一定有其他问题,比如 .Property(x => x.Gender) 或类似的问题。 - Ivan Stoev
1
很抱歉,我忘记在问题中添加一行代码,实际上这导致了问题。user.HasIndex(x => x.Gender); 我试图在一个导航属性上创建索引。我不得不将其更改为 user.HasIndex(x => x.GenderId); - Nimish David Mathew
5个回答

48

我试图在导航属性上创建索引,但实际上应该在外键上创建索引。

user.HasIndex(x => x.Gender)更改为user.HasIndex(x => x.GenderId)


2

由于类似问题的更新:

当我尝试建立下面实体之间的关系时,遇到了与您类似的问题:产品(Product)实体和保修(Warranti)实体:

public class Product
{
    public long Id { get; set; }
    public string Images { get; set; }
    public string Brand { get; set; }
    public Warranti Warranti { get; set; }
}


public class Warranti
{
    public Product Product { get; set; }
    public long ProductId { get; set; }
    public int WarrantyPeriod { get; set; }
}

而在我的 DatabaseContext 类中,我有这个配置:

  protected override void OnModelCreating(ModelBuilder modelBuilder)  
   {
        modelBuilder.Entity<Product>()
            .HasOne(p => p.Warranti)
            .WithOne(p => p.Product)
            .HasForeignKey<Warranti>(p => p.Product);
    }

我也遇到了同样的错误。但是,问题出在哪里呢?

根据微软官方 EFCore 文档,ForeignKey 应该像这样:

.HasForeignKey(p => p.BlogForeignKey); // single prop such as string or int,...

或者

 .HasForeignKey("BlogForeignKey"); // Hardcoded favorite string

但是我在HasForeignKey方法中使用了一个类(a class(Product)),而不是一个属性。同样地,你在HasIndex方法中使用了一个类(a class(Gender)),而不是一个属性。将这些类更改为Id属性可以解决问题。
总之,尝试在HasForeignKey()HasIndex()中使用Id属性。

1
我在一个复杂的层次结构模型中遇到了同样的问题,其中嵌套了复杂的类。
显然,IsRequired() 方法与 OnDelete(...) 冲突。我删除了 IsRequired(),一切恢复正常。
public class MyComplexClassConfig : IEntityTypeConfiguration<MyComplexClass>
{
    public void Configure(EntityTypeBuilder<MyComplexClass> builder)
    {
        builder
            .HasOne(col => col.ChildClass)
            .WithOne(col => col.ParentClass)
            .OnDelete(DeleteBehavior.Cascade);
            
        // The following line of code needs to be deleted.
        builder.Property(col => col.Customer).IsRequired();
    }
}

1
在您的 public virtual Gender Gender { get; set; } 属性上使用 [ForeignKey("GenderId")]。因此,GenderId 将被标识为关联用户的外键。
请参阅以下更新的代码:
public class User
{
    public int GenderId { get; set; }
    [ForeignKey("Id")]//Gender Primary key
    public virtual Gender Gender { get; set; }
}

希望能解决你的问题。
谢谢,

4
DbContext 中,.HasForeignKey(x => x.GenderId); 不是做同样的事情吗? - Nimish David Mathew

1

我遇到了类似的错误:

'Product' 不能作为实体类型 'OrderLine' 上的属性使用,因为它被配置为导航。

错误的原因是在 Fluent API 中我也将实体用作了属性:

modelBuilder.Entity<OrderLine>().Property(ol => ol.Product).IsRequired(true)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接