.NET MVC EF中同一两表间一对多与多对多关系配置报错
你遇到的问题是EF对新增的「用户所属公司」关系的** multiplicity(关系基数)**推断错误了,我来帮你理清楚问题根源并给出解决方案:
错误原因分析
你在Company模型里添加的public virtual ApplicationUser user { get; set; }是单个导航属性,EF会默认把它和用户模型里的public virtual Company company { get; set; }推断为一对一关系。但一对一关系有严格要求:依赖端(这里是用户表)的外键必须是主键或唯一键,而你的Id_company是可选的非主键字段,完全不符合这个规则,所以EF抛出了那个错误——提示依赖端的multiplicity上限必须是*(也就是一对多的「多」端)。
另外你之前尝试的[InverseProperty("usuarios")]没生效,是因为Company里对应的属性名是user而非usuarios,更关键的是属性类型不对(应该是集合而非单个对象)。
正确的配置步骤
1. 修改Company模型的导航属性
一个公司可以有多个用户把它设为所属公司,所以Company里的导航属性应该是集合类型,并且取一个和多对多关系的users不同的名字,避免EF混淆两个关系:
// 替换原来的public virtual ApplicationUser user { get; set; } public virtual ICollection<ApplicationUser> UsersWithPrimaryCompany { get; set; }
2. 修正用户模型的注解(可选,或用Fluent API)
在用户模型的导航属性上加上[InverseProperty],明确指向Company里的集合属性,让EF清晰区分开「多对多的访问关系」和「一对多的所属关系」:
[ForeignKey("Id_company")] [Display(Name = "Company")] [InverseProperty("UsersWithPrimaryCompany")] // 对应Company里的集合属性名 public int? Id_company { get; set; } public virtual Company company { get; set; }
3. 推荐:用Fluent API更清晰地配置关系
如果你觉得数据注解容易混淆,直接在OnModelCreating里用Fluent API配置这个一对多关系,同时保留原来的多对多配置:
// 原有的多对多配置保持不变 modelBuilder.Entity<ApplicationUser>() .HasMany<Company>(s => s.companies) .WithMany(c => c.users) .Map(cs => { cs.MapLeftKey("id_user"); cs.MapRightKey("id_company"); cs.ToTable("users_companies"); }); // 新增的用户所属公司一对多关系配置 modelBuilder.Entity<ApplicationUser>() .HasOptional(u => u.company) // 用户可选拥有一个所属公司 .WithMany(c => c.UsersWithPrimaryCompany) // 一个公司可以对应多个用户的所属公司 .HasForeignKey(u => u.Id_company) .WillCascadeOnDelete(false); // 可选:防止删除公司时连带删除用户,根据业务需求调整
最后执行迁移
做完上面的修改后,重新生成迁移并执行update-database,应该就能正常运行了。
内容的提问来源于stack exchange,提问作者patsy2k

