EF Core 7.0中DbSet<SassyUser>查询抛出InvalidCastException类型转换异常
核心原因
最可能是EF Core的继承映射配置出现混淆:因为SassyUser和SassyDataset都继承自抽象基类IdentifiedObjectBase,如果配置时没明确区分二者的映射规则,EF可能默认启用了TPH(Table Per Hierarchy)单表继承策略,把两个实体的记录存在同一张表,用自动生成的鉴别器区分。一旦鉴别器配置错误、缺失,或者你实际是想让两个实体用独立表,EF查询时就会把所有派生类实例都尝试转换成你请求的SassyUser类型,从而抛出类型转换异常。
另外也可能是实体配置类的映射逻辑搞混,比如不小心把SassyDataset的配置应用到了SassyUser上,或者基类的配置错误地指定了表,导致EF的实体类型映射出错。
解决步骤
1. 强制每个实体使用独立表(推荐)
在各自的IEntityTypeConfiguration配置类中,明确指定实体对应的表名,避免EF默认合并成单表:
// SassyUser的配置类 public class SassyUserConfiguration : IEntityTypeConfiguration<SassyUser> { public void Configure(EntityTypeBuilder<SassyUser> builder) { // 明确绑定到独立表 builder.ToTable("SassyUsers"); // 其他属性配置 builder.HasKey(u => u.Id); builder.Property(u => u.UserName).IsRequired().HasMaxLength(64); // ...其他属性 } } // SassyDataset的配置类 public class SassyDatasetConfiguration : IEntityTypeConfiguration<SassyDataset> { public void Configure(EntityTypeBuilder<SassyDataset> builder) { builder.ToTable("SassyDatasets"); builder.HasKey(d => d.Id); builder.Property(d => d.DatasetName).IsRequired().HasMaxLength(128); // ...其他属性 } }
2. 修正基类的配置
如果基类IdentifiedObjectBase有单独的配置类,确保它是抽象基类的通用配置,不绑定到具体表:
public class IdentifiedObjectBaseConfiguration : IEntityTypeConfiguration<IdentifiedObjectBase> { public void Configure(EntityTypeBuilder<IdentifiedObjectBase> builder) { // 只配置基类的通用属性,不要调用ToTable() builder.HasKey(o => o.Id); builder.Property(o => o.CreatedAt).IsRequired(); builder.Property(o => o.UpdatedAt).IsRequired(false); } }
然后在DbContext的OnModelCreating中,正确加载所有配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ApplyConfiguration(new IdentifiedObjectBaseConfiguration()); modelBuilder.ApplyConfiguration(new SassyUserConfiguration()); modelBuilder.ApplyConfiguration(new SassyDatasetConfiguration()); // 其他配置逻辑 }
3. 清理迁移并重建数据库
如果之前的迁移文件有残留的错误配置,删除现有迁移文件,重新生成初始迁移并更新数据库:
# 手动删除项目中的Migrations文件夹后执行以下命令 dotnet ef migrations add InitialCreate dotnet ef database update
4. 检查鉴别器配置(如果确实要用TPH)
如果你故意想使用单表继承(TPH),必须明确配置鉴别器,确保EF能正确区分两个实体:
// 在基类配置中添加鉴别器 public class IdentifiedObjectBaseConfiguration : IEntityTypeConfiguration<IdentifiedObjectBase> { public void Configure(EntityTypeBuilder<IdentifiedObjectBase> builder) { builder.ToTable("IdentifiedObjects"); // 单表名 builder.HasKey(o => o.Id); // 配置鉴别器列和对应值 builder.HasDiscriminator<string>("EntityType") .HasValue<SassyUser>("SassyUser") .HasValue<SassyDataset>("SassyDataset"); } }
同时确保数据库中EntityType列的值和配置一致,查询时EF会根据鉴别器值返回正确的实体类型。
5. 验证Pomelo版本兼容性
确保你使用的Pomelo.EntityFrameworkCore.MySql版本是7.0.x,和EF Core 7.0完全兼容,版本不匹配也可能导致映射逻辑异常。
内容的提问来源于stack exchange,提问作者Jean-Louis Arnal

