Entity Framework:使用Fluent API配置一对多关系时出现验证错误
解决EF Fluent API一对多关系的验证错误
这个错误的核心原因很明确:你给ApplicationStore设置了复合主键(StoreId + Name),但在配置一对多关联时,StoreAction只通过单一的StoreId作为外键,这违反了EF的约束规则——外键的属性数量必须和关联的主键属性数量完全一致。
下面分两种场景给出解决方案:
场景1:确实需要ApplicationStore使用复合主键
如果你的业务逻辑要求必须同时用StoreId和Name来唯一标识一个商店,那需要修改StoreAction模型,添加对应于主键第二个字段的外键属性,然后重新配置关联:
第一步:更新StoreAction模型
public class StoreAction { public int ActionId { get; set; } public int StoreId { get; set; } public string StoreName { get; set; } // 添加这个字段,对应ApplicationStore的Name主键 public string ActionName { get; set; } public string ActionRoute { get; set; } public string RequestType { get; set; } public virtual ApplicationStore Store { get; set; } }
第二步:修改Fluent API配置
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // 保留ApplicationStore的复合主键配置 modelBuilder.Entity<ApplicationStore>().HasKey(m => new { m.StoreId, m.Name }); modelBuilder.Entity<ApplicationStore>().Property(t => t.StoreId).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); modelBuilder.Entity<ApplicationStore>().Property(m => m.Name).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None); modelBuilder.Entity<StoreAction>().HasKey(m => m.ActionId); modelBuilder.Entity<StoreAction>().Property(m => m.ActionId).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); // 配置复合外键,同时关联StoreId和StoreName modelBuilder.Entity<ApplicationStore>() .HasMany(a => a.Actions) .WithRequired(s => s.Store) .HasForeignKey(s => new { s.StoreId, s.StoreName }); base.OnModelCreating(modelBuilder); }
场景2:StoreId本身即可唯一标识ApplicationStore(更常见)
如果这是一个配置错误——StoreId作为自增ID已经可以唯一区分商店,那只需要修正ApplicationStore的主键配置即可,原来的关联逻辑不需要改动:
修改Fluent API配置
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // 将复合主键改为单一主键StoreId modelBuilder.Entity<ApplicationStore>().HasKey(m => m.StoreId); modelBuilder.Entity<ApplicationStore>().Property(t => t.StoreId).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); // Name字段的配置可以保留,但不再作为主键 modelBuilder.Entity<ApplicationStore>().Property(m => m.Name).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None); modelBuilder.Entity<StoreAction>().HasKey(m => m.ActionId); modelBuilder.Entity<StoreAction>().Property(m => m.ActionId).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); // 原来的一对多关联配置现在可以正常工作 modelBuilder.Entity<ApplicationStore>() .HasMany(a => a.Actions) .WithRequired(s => s.Store) .HasForeignKey(s => s.StoreId); base.OnModelCreating(modelBuilder); }
本质上,EF会严格校验关系两端的键属性数量是否匹配,只要对齐主键和外键的属性数量,这个错误就会消失。
内容的提问来源于stack exchange,提问作者Haider Khalid
相关产品推荐
相关产品推荐

