EF Core 7报错:实体类型'List<string>'需定义主键,求解决
EF Core 7 实体创建报错:“实体类型'List'需要定义主键”的解决方法
问题描述
使用EF Core 7创建实体时触发报错:
实体类型'List
'需要定义主键。若要使用无键实体类型,请在OnModelCreating中调用HasNoKey
排查发现,注释Service实体的Project属性后,Add-Migration可成功执行,但不清楚报错原因及修复方案。
报错原因
问题根源在于EntityBase抽象类中的ValueChangedProperties属性:
该属性标记了[NotMapped],但同时带有virtual修饰符。当EF Core处理继承自EntityBase的实体(如Project)的导航属性时,会错误地将这个虚拟集合属性识别为需要映射的实体类型,而非忽略属性。
当Service实体包含Project导航属性时,EF Core遍历Project的属性时,会把virtual List<string>当成需要映射的实体集合,而List<string>没有主键定义,因此触发报错。注释Service的Project属性后,EF Core不再处理Project实体的导航关联,也就不会触发这个识别错误。
修复方案
方案1:移除虚拟修饰符
直接去掉ValueChangedProperties和Snapshot的virtual修饰符,让EF Core正确识别[NotMapped]标记:
[NotMapped] public EntityBase Snapshot { get; set; } [NotMapped] public List<string> ValueChangedProperties { get; set; } = new List<string>();
方案2:显式配置忽略属性
若必须保留virtual(如依赖动态代理场景),在OnModelCreating中为所有继承自EntityBase的实体显式忽略这两个属性:
protected override void OnModelCreating(ModelBuilder modelBuilder) { var entityTypes = typeof(TestDbContext).GetProperties() .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)) .Select(p => p.PropertyType.GetGenericArguments()[0]).ToList(); entityTypes.ForEach(entityType => { var entityName = entityType.Name; modelBuilder.Entity(entityType).ToTable(entityName); // 显式忽略无需映射的属性 if(typeof(EntityBase).IsAssignableFrom(entityType)) { modelBuilder.Entity(entityType).Ignore(nameof(EntityBase.Snapshot)); modelBuilder.Entity(entityType).Ignore(nameof(EntityBase.ValueChangedProperties)); } }); modelBuilder.Entity<ServiceMapping>().HasOne(x => x.Service).WithMany().HasForeignKey(x => x.ServiceId).OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity<ServiceMapping>().HasOne(x => x.TargetService).WithMany().HasForeignKey(x => x.TargetServiceId).OnDelete(DeleteBehavior.Cascade); base.OnModelCreating(modelBuilder); }
内容的提问来源于stack exchange,提问作者eleven
相关产品推荐
相关产品推荐

