You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在EntityFramework Core 7中无需DataSet执行原生SQL查询

EF Core 7 原生SQL查询无对应表模型的解决方案

无键实体类型:完全可行,且无需绑定原表

无键实体类型(Keyless Entity Types)就是专门用来处理这种“数据库中不存在对应表,但需要映射SQL查询结果”的场景,完全不需要为原表建模型,也不用在OnModelCreating里做表绑定配置,只需要简单两步:

  1. 定义一个仅用来接收查询结果的模型类(数据库里没有这个表):
public class CustomQueryResult
{
    public string UserName { get; set; }
    public int OrderCount { get; set; }
    public decimal TotalAmount { get; set; }
}
  1. 在你的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:52:23