EF Core 7及以下版本使用原生SQL查询未映射类型的问题
1. EF Core 查询未映射类型的版本支持
EF Core 8是首个原生支持用Database.SqlQuery<T>直接查询未映射类型(即未在DbContext中配置DbSet或实体映射的类)的版本。
在EF Core 8之前,无法直接通过这个方法查询未映射类型,但有替代方案:
- 使用
FromSqlRaw/FromSql配合自定义DTO(若是已映射实体,直接用DbSet的对应方法即可) - 手动通过ADO.NET执行查询,再将结果映射为对象
而EF6中的SqlQuery<T>确实无需额外配置就能查询未映射类型,这是EF6与EF Core(8版本之前)的设计差异。
2. 你的代码报错原因及解决办法
从你的实体配置可以看出,Order是已映射到数据库表的实体(存在DbSet<Order>且在OnModelCreating中配置了表结构),但你使用了Database.SqlQuery<Order>,这在非EF Core 8版本中会报错——因为旧版本的该方法不支持已映射的实体类型。
解决方式:
如果你的EF Core版本低于8,应使用DbSet的FromSql或FromSqlRaw方法查询已映射实体:
List<Order> order = await _BSDB.Orders .FromSql($"select * from BikeStore.sales.orders") .ToListAsync();
若你使用的是EF Core 8仍报错,可能是Order实体的映射配置与查询返回的字段不匹配,或是需要确认相关配置是否启用。另外,EF Core 8中Database.SqlQuery<T>主要针对未映射类型,已映射实体仍推荐使用DbSet.FromSql。
如果确实要在EF Core 8中用Database.SqlQuery<T>查询已映射类型,可通过ModelConfigurationBuilder.DefaultTypeMapping配置映射(但这一般是为未映射类型准备的):
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { configurationBuilder.DefaultTypeMapping<Order>(); }
不过更合理的做法还是对已映射实体使用DbSet的查询方法,无需额外配置。
内容的提问来源于stack exchange,提问作者Adhiraj Kinlekar

