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

EF Core 8如何将原生SQL查询映射到含复杂类型的非实体类?

EF Core 8原生SQL查询映射复杂嵌套类型的实用方案

针对你提到的场景——用原生SQL查询结果映射到包含嵌套复杂类型的对象(类A包含类B属性),EF Core 8确实有不用低级数据读取器的简洁方案,下面两种方法都能解决问题:

方法1:通过中间DTO做投影转换

这是最通用的方案,不管B是不是EF映射的类型都能用。步骤很简单:

  1. 先定义一个平结构的中间DTO,把SQL返回的所有字段都包含进去:
public class AFlatDto
{
    public int Id { get; set; }
    public int IdB { get; set; }
    public string Description { get; set; }
}
  1. 用SqlQuery查询这个DTO,再通过LINQ的Select手动组装成嵌套的A和B对象:
var sql = @"SELECT a.Id, b.IdB, b.Description 
            FROM TableA a 
            JOIN TableB b ON a.BId = b.IdB 
            WHERE a.Id = @Id";

var queryResult = context.Database.SqlQuery<AFlatDto>(sql, new SqlParameter("@Id", 1));

var finalResult = queryResult.Select(dto => new A
{
    Id = dto.Id,
    B = new B
    {
        IdB = dto.IdB,
        Description = dto.Description
    }
}).ToList();

为什么不用SqlQueryRaw<dynamic>?因为dynamic类型无法自动识别嵌套属性的映射规则,强类型的DTO能让EF准确映射SQL字段,再手动转换到目标类型就很稳妥。

方法2:配置复杂类型直接映射

如果B可以被定义为EF的值对象/复杂类型(没有独立主键,完全依赖于A存在),可以直接让EF自动映射嵌套属性:

  1. 在DbContext的OnModelCreating里配置A的B属性为复杂类型:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<A>().OwnsOne(a => a.B);
}
  1. 调整SQL返回的字段名,和EF默认生成的复杂类型列名匹配(格式为[嵌套属性名_子属性名]),然后直接查询A类型:
var sql = @"SELECT a.Id, 
                   b.IdB AS [B_IdB], 
                   b.Description AS [B_Description] 
            FROM TableA a 
            JOIN TableB b ON a.BId = b.IdB 
            WHERE a.Id = @Id";

var result = context.Database.SqlQuery<A>(sql, new SqlParameter("@Id", 1)).ToList();

这样EF会自动把B_IdB和B_Description映射到A的B属性对应的子字段里,不需要手动转换。

注意:优先用SqlQuery而不是SqlQueryRaw,前者支持参数化查询,能避免SQL注入风险。

内容的提问来源于stack exchange,提问作者Luis Abreu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:07:03