EF Core与其他外键属性之间的一对多关系

时间:2019-09-12 06:11:43

标签: c# asp.net-core .net-core ef-core-2.2

我有这两个模型(不存在不相关的属性):

// based on Identity
public class User {
  public long? CityId { get; set; }
  public virtual City City { get; set; }
}

public class City : Base {
}

public class Base {
  public string CreatorId { get; set; }
  public virtual User Creator { get; set; }
}

现在,问题在于EF Core无法确定UserCity之间的一对多关系,并且它认为存在一对一关系(我记得我EF 6并没有这样的问题。

  

无法一一确定孩子/受抚养人的一面   “ User.City”和“ City.Creator”之间的关系。识别   子/依赖关系的一方,配置外键   属性。如果这些导航不应属于同一导航   关系可以在不指定逆数的情况下配置它们。

因此,我被迫向City添加另一个导航属性:

public class City : Base {
  public virtual IList<User> Users { get; set; }
}

但是问题仍然存在:

  

无法确定导航所代表的关系   “ IList”类型的媒体资源“ City.Users”。手动配置   关系,或使用“ [NotMapped]”忽略此属性   属性,或使用“ OnModelCreating”中的“ EntityTypeBuilder.Ignore”。

我最终使用了Fluent API和ModelBuilder

modelBuilder.Entity<User>()
            .HasOne<City>(u => u.City)
            .WithMany(c => c.Users)
            .HasForeignKey(u => u.CityId);

使用Fluent API,我们可以删除Users内的City导航属性,并调用一个空的WithMany(请参阅第一个注释):

modelBuilder.Entity<User>()
            .HasOne<City>(u => u.City)
            .WithMany()
            .HasForeignKey(u => u.CityId);

这是唯一的方法吗?我在做错什么吗?

编辑:我在EF 6版本的CreatorId类上拥有更多的属性,例如LastEditorId(例如Base),它仍然可以关系。在EF Core版本中对此进行了尝试。无法正常工作。

1 个答案:

答案 0 :(得分:1)

问题似乎是从City模型继承的Base包含父类的所有属性,因此CityUser之间的关系是一对一的,而不是一对多的。

实际上,Entity Framework Core对于一对多关系遵循与Entity Framework 6.x约定相同的约定。唯一的区别是EF Core创建的外键列的名称与导航属性名称相同,而不是<NavigationPropertyName>_<PrimaryKeyPropertyName>

Fluent API指定您可以通过数据注释使用的模型配置,以及一些数据注释无法实现的附加功能。

  • 在Entity Framework Core中,ModelBuilder类充当Fluent API。

  • 我们可以使用它来配置许多不同的东西,因为它提供了比数据注释属性更多的配置选项。

  • 数据注释和fluent API可以一起使用,但是 Fluent API>数据注释>默认约定优先。

您可以参考以下链接,以帮助您更好地理解Fluent Api:

https://www.entityframeworktutorial.net/efcore/fluent-api-in-entity-framework-core.aspx

https://entityframeworkcore.com/model-fluent-api