EF6使用DbSet.SqlQuery查询TPH继承实体时遇抽象类实例化错误
解决EF6中TPH抽象基类使用SqlQuery报错的问题
这个问题我之前在处理EF6的单表继承(TPH)结构时也踩过坑,核心原因很明确:你调用的DbSet<myBaseClass>.SqlQuery()会尝试直接实例化抽象基类myBaseClass,但抽象类本身是不能被实例化的,哪怕数据库里存的是具体子类的数据,EF也不会自动根据TPH的鉴别器列去创建对应的子类实例。
推荐解决方案:用LINQ查询替代SqlQuery
如果你只是想一次性查询一组ID的实体,完全没必要用原生SQL,直接用LINQ的Where+Contains就能解决问题,而且EF会自动处理TPH的子类实例化:
// 假设你有一个存放目标ID的集合 List<int> targetIds = /* 你的ID列表 */; List<myBaseClass> myResult = myContext.myHierarchy .Where(entity => targetIds.Contains(entity.id)) .ToList();
这种方式的优势在于:
- EF会自动生成优化的SQL语句(通常是带IN子句的查询)
- 会根据TPH的鉴别器列,自动实例化对应的具体子类,完全避开抽象类创建的问题
- 代码更简洁易维护
必须使用表值参数的场景?这样处理
如果因为ID数量过多(超过SQL IN子句的参数限制),必须用用户定义表类型来查询,那可以通过“先查临时对象,再手动映射子类”的方式解决:
- 先定义一个临时类来接收SQL查询的结果(包含鉴别器列和所有属性):
public class TempHierarchyItem { public int id { get; set; } // TPH的鉴别器列,名字要和数据库里的一致 public string Discriminator { get; set; } // 添加基类和所有子类的公共属性 public string CommonProp { get; set; } public int AnotherCommonProp { get; set; } // 子类特有的属性也要加上 public string SubClassAProp { get; set; } public int SubClassBProp { get; set; } }
- 用
Database.SqlQuery执行查询,得到临时对象集合:
var tempItems = myContext.Database.SqlQuery<TempHierarchyItem>(@" SELECT a.* FROM dbo.myHierarchy AS a INNER JOIN @theIDs AS i ON a.id = i.id", mySqlParameter).ToList();
- 根据鉴别器列的值,手动实例化对应的子类并转换为基类集合:
List<myBaseClass> myResult = tempItems.Select(item => { return item.Discriminator switch { nameof(SubClassA) => new SubClassA { id = item.id, CommonProp = item.CommonProp, AnotherCommonProp = item.AnotherCommonProp, SubClassAProp = item.SubClassAProp }, nameof(SubClassB) => new SubClassB { id = item.id, CommonProp = item.CommonProp, AnotherCommonProp = item.AnotherCommonProp, SubClassBProp = item.SubClassBProp }, _ => throw new NotSupportedException($"不支持的鉴别器类型:{item.Discriminator}") }; }).ToList();
为什么你的原始代码会报错?
因为myContext.myHierarchy是DbSet<myBaseClass>,调用SqlQuery时,EF会直接尝试创建myBaseClass的实例——但它是抽象类,不符合实例化的要求,所以抛出了InvalidOperationException: Instances of abstract classes cannot be created.的错误。而LINQ查询会让EF自动识别TPH的鉴别器列,选择正确的子类进行实例化,所以不会有这个问题。
内容的提问来源于stack exchange,提问作者donquijote
相关产品推荐
相关产品推荐

