如何修复实体框架中的“无法确定导航属性表示的关系”错误

Posted

技术标签:

【中文标题】如何修复实体框架中的“无法确定导航属性表示的关系”错误【英文标题】:How to fix 'Unable to determine the relationship represented by navigation property' error in Entity Framework 【发布时间】:2019-09-01 21:22:56 【问题描述】:

当我尝试在我的 .NET Core 2.1 网站上注册用户(使用身份)时,我收到以下错误:

“InvalidOperationException:无法确定由“ICollection”类型的导航属性“City.ConnectionStartCity”表示的关系。手动配置关系,或使用“[NotMapped]”属性或使用“EntityTypeBuilder”忽略此属性。 'OnModelCreating' 中的忽略'。”。

发生这种情况的原因可能与身份无关,但注册和登录是目前我知道如何触发它的唯一方法。

我仍然希望在我的课程中使用“City”和“ICollection”属性,所以我不想使用“[NotMapped]”属性。

我在网上搜索,发现这是多对多关系造成的,我觉得不是这样。

“连接”类:

public partial class Connection
    
        public Connection()
        
            ConnectionRoute = new HashSet<ConnectionRoute>();
        

        public int Id  get; set; 
        public int StartCityId  get; set; 
        public int EndCityId  get; set; 
        public int AantalMinuten  get; set; 
        public double Prijs  get; set; 

        public Stad StartCity  get; set; 
        public Stad EndCity  get; set; 
        public ICollection<ConnectionRoute> ConnectionRoute get; set; 
    

“城市”类:


public partial class City
    
        public City()
        
            AspNetUsers = new HashSet<AspNetUsers>();
            Hotel = new HashSet<Hotel>();
            ConnectionStartCity = new HashSet<Connection>();
            ConnectionEndCity= new HashSet<Connection>();
        

        public int Id  get; set; 
        public string Name  get; set; 
        public string Country  get; set; 

        public ICollection<AspNetUsers> AspNetUsers  get; set; 
        public ICollection<Hotel> Hotel  get; set; 
        public ICollection<Connection> ConnectionStartCity  get; set; 
        public ICollection<Connection> ConnectionEndCity  get; set; 
    

类 'treinrittenContext' (dbContext) 提取:

public virtual DbSet<City> City get; set; 

public virtual DbSet<Connection> Connection get; set; 

protected override void OnModelCreating(ModelBuilder modelBuilder)
        
            ...

            modelBuilder.Entity<City>(entity =>
            
                entity.Property(e => e.Country)
                    .IsRequired()
                    .HasMaxLength(255)
                    .IsUnicode(false);

                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(255)
                    .IsUnicode(false);

                entity.HasMany(p => p.ConnectionStartcity)
                    .WithOne(d => d.StartCity)
                    .HasForeignKey(d => d.StartCityId);

                entity.HasMany(p => p.ConnectionEndCity)
                    .WithOne(d => d.EndCity)
                    .HasForeignKey(d => d.EndCityId);
            );

            ...

            modelBuilder.Entity<Connection>(entity =>
            
                entity.HasOne(d => d.StartCity)
                    .WithMany(p => p.ConnectionStartCity)
                    .HasForeignKey(d => d.StartCityId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_Verbinding_BeginStad");

                entity.HasOne(d => d.EndCity)
                    .WithMany(p => p.ConnectionEndCity)
                    .HasForeignKey(d => d.EndCityId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_Verbinding_EindStad");
            );

            ...
        

我希望这会起作用(因为在我看来,这是一对多的关系),但事实并非如此。

【问题讨论】:

您还应该考虑您的命名,集合应该是多个(meervoud),例如您的 DbSet 应该是 Connections 和 Cities 以及您的属性 ConnectionStartCity 和 ConnectionEndCity。至于错误,可能是因为您缺少 StartCity 和 EndCity 上的 [必需] 注释。 @Dimitri,感谢您提供有关命名约定的提示。在 Connection 中为 StartCity 和 EndCity 添加 [Required] 注释并没有解决。 【参考方案1】:

更新

这里有多种选择:

选项 1 结果为 1

城市等级变为:

public partial class City

    public City()
               
        Connections = new HashSet<Connection>();
    

    public int Id  get; set; 
    public string Name  get; set; 
    public string Country  get; set; 

    public ICollection<Connection> Connections  get; set; 

连接类变为:

public partial class Connection

    public Connection()
    
    

    public int Id  get; set; 

    public int StartCityId  get; set; 
    public int EndCityId  get; set; 

    public int AantalMinuten  get; set; 
    public double Prijs  get; set;      

您的 OnModelCreating 变为:

modelBuilder.Entity<City>().HasMany(city => city.Connections)
                           .WithRequired().HasForeignKey(con => con.EndCityId);

modelBuilder.Entity<City>().HasMany(city => city.Connections)
                           .WithRequired().HasForeignKey(con => con.StartCityId);

或者您也可以执行类似的操作,其中选项 2 的结果为 2:

城市等级变为:

public partial class City

    public City()
               
        Connections = new HashSet<Connection>();
    

    public int Id  get; set; 
    public string Name  get; set; 
    public string Country  get; set; 

    public ICollection<Connection> Connections  get; set; 

连接类变为:

public partial class Connection

    public Connection()
    
    

    public int Id  get; set; 

    public virtual ICollection<City> Cities  get; set; 

    public int AantalMinuten  get; set; 
    public double Prijs  get; set;      

而且您无需在 OnModelCreating 中执行任何操作。

【讨论】:

我刚刚意识到我在我的问题中留下了一些未翻译的单词。那是我对不起!我更新了它,所以现在它应该更有意义了。 City 只是一个城市表(在我的例子中是伦敦,布鲁塞尔,......),连接应该是 2 个城市之间的连接(例如“伦敦到布鲁塞尔”或“布鲁塞尔到巴黎”)。因此,在 City 中,我想要一个以城市为起点的连接列表和一个以城市为终点的连接列表。完整的数据库模型(Stad = City 和 Verbinding = Connection):gyazo.com/8211bb2789e0f7a864aee1a6b9e21192 当我尝试第一个选项时,我在构建时收到此错误:“无法在 'City.Connection' 和 'Connection.EndCity' 之间创建关系,因为 'City.Connection' 之间已经存在关系。 Connection' 和 'Conncection.StartCity'。导航属性只能参与单个关系。”使用第二种解决方案,我失去了哪个城市是起点,哪个城市是终点。在这种情况下,它们的顺序很重要。 收集城市应该是虚拟的。 我同意第二种解决方案不适用于您的情况。至于错误,奇怪,没有发生在我这边。您是否启用了迁移?如果是这样,请更新您的模型。如果没有,你能告诉我你的 onmodelcreating 有什么,最终你的类现在是什么样子吗? @Dimitri 感谢您的回复

以上是关于如何修复实体框架中的“无法确定导航属性表示的关系”错误的主要内容,如果未能解决你的问题,请参考以下文章

修复实体框架“无法确定关系...”的问题

如何修复 Java 中的“禁用 XML 外部实体 (XXE) 处理”漏洞

如何修复 Node.js 中的“413 请求实体太大”错误

使用实体框架中的可选记录级联删除

如何修复 ApplicationUserManager 中的“LINQ to Entities 中不支持指定的类型成员‘UserId’”

实体框架中的用户定义表生成不正确的查询