如何在EntityFramework Core 7中无需DataSet执行原生SQL查询
EF Core 7 原生SQL查询无对应表模型的解决方案
无键实体类型:完全可行,且无需绑定原表
无键实体类型(Keyless Entity Types)就是专门用来处理这种“数据库中不存在对应表,但需要映射SQL查询结果”的场景,完全不需要为原表建模型,也不用在OnModelCreating里做表绑定配置,只需要简单两步:
- 定义一个仅用来接收查询结果的模型类(数据库里没有这个表):
public class CustomQueryResult { public string UserName { get; set; } public int OrderCount { get; set; } public decimal TotalAmount { get; set; } }
- 在你的DbContext里声明这个无键实体的DbSet,用
[Keyless]特性标记即可(不用做任何表关联配置):
public class AppDbContext : DbContext { // 仅作为SQL查询结果的载体,不对应数据库表 [Keyless] public DbSet<CustomQueryResult> CustomQueryResults { get; set; } // 其他原有DbSet和上下文配置... }
之后就能直接用EF的FromSqlRaw/FromSqlInterpolated执行原生SQL,自动映射到这个模型:
using var dbContext = new AppDbContext(); var sql = @" SELECT u.UserName, COUNT(o.Id) as OrderCount, SUM(o.Amount) as TotalAmount FROM Users u LEFT JOIN Orders o ON u.Id = o.UserId GROUP BY u.UserName "; var results = dbContext.CustomQueryResults.FromSqlRaw(sql).ToList();
核心逻辑是:无键实体只是EF用来解析SQL结果的容器,和数据库原有表没有任何绑定关系,完全符合你的需求。
辅助类方案:要不要用EF?看你需求
辅助类本质是用ADO.NET直接执行SQL、手动读取数据映射模型,确实可以脱离EF,但用EF的好处也很明确:
- 复用DbContext的连接配置,不用自己写连接字符串、管理连接生命周期;
- 如果后续要对查询结果做分页、过滤等LINQ操作,无键实体方案可以无缝衔接;
- 自动处理数据类型映射,不用手动转换
SqlDataReader的字段值。
如果只是单纯跑一次SQL拿数据,用ADO.NET辅助类没问题;但想省掉连接管理、类型转换的麻烦,还是推荐无键实体方案。
要是连在DbContext里加DbSet都嫌麻烦,也可以直接用EF上下文拿连接,走纯ADO.NET流程:
using var dbContext = new AppDbContext(); using var connection = dbContext.Database.GetDbConnection(); await connection.OpenAsync(); using var command = connection.CreateCommand(); command.CommandText = @" SELECT u.UserName, COUNT(o.Id) as OrderCount, SUM(o.Amount) as TotalAmount FROM Users u LEFT JOIN Orders o ON u.Id = o.UserId GROUP BY u.UserName "; using var reader = await command.ExecuteReaderAsync(); var results = new List<CustomQueryResult>(); while (await reader.ReadAsync()) { results.Add(new CustomQueryResult { UserName = reader.GetString(reader.GetOrdinal("UserName")), OrderCount = reader.GetInt32(reader.GetOrdinal("OrderCount")), TotalAmount = reader.GetDecimal(reader.GetOrdinal("TotalAmount")) }); }
总结:
- 想保留EF的便利,选无键实体类型,只需加个标记了Keyless的DbSet;
- 想完全脱离EF实体管理,直接用ADO.NET辅助类手动处理。
内容的提问来源于stack exchange,提问作者techno
相关产品推荐
相关产品推荐

