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

.NET Core调用多结果集SQL Server存储过程获取第二张表数据

问题根因

EF Core 原生的FromSqlInterpolated绑定到单个DbSet<T>时,只会消费存储过程返回的第一个结果集,后续SELECT返回的数据会被直接丢弃。你尝试把DbSet泛型改成组合DTO的思路走不通,是因为EF Core的FromSql映射不支持自动拆分多个结果集到DTO的不同属性,这类多结果集场景必须手动处理数据读取。

正确实现方式

你不需要在DbContext里给存储过程专门留一个DbSet,多结果集场景下这种写法没用,按下面步骤操作即可:

  1. 先定义对应第二个结果集的实体,以及最终要返回的组合结构
// 对应存储过程第二个SELECT返回的字段
public class Media
{
    public int Id { get; set; }
    public string Url { get; set; }
}

// 组合两个结果集的返回DTO
public class PropertyQueryResult
{
    public List<Property> Properties { get; set; }
    public List<Media> RelatedMedia { get; set; }
}
  1. 直接通过EF Core拿到底层数据库连接,执行存储过程后手动按顺序读取两个结果集,代码如下:
// 定义参数,和你原有参数写法保持一致
var point = new SqlParameter("postCodePointBinary", System.Data.SqlDbType.NVarChar, 500) 
{ 
    Value = string.IsNullOrEmpty(locationIdString) ? (object)DBNull.Value : locationIdString 
};
var radius = new SqlParameter("radius", System.Data.SqlDbType.Float) 
{ 
    Value = filters.Radius 
};

var queryResult = new PropertyQueryResult();
var dbConnection = _context.Database.GetDbConnection();

try
{
    if (dbConnection.State != System.Data.ConnectionState.Open)
        dbConnection.Open();

    using var command = dbConnection.CreateCommand();
    command.Connection = dbConnection;
    command.CommandText = "spGetProperties";
    command.CommandType = System.Data.CommandType.StoredProcedure;
    command.Parameters.Add(radius);
    command.Parameters.Add(point);

    using var reader = command.ExecuteReader();

    // 读取第一个结果集:符合条件的房产列表
    var properties = new List<Property>();
    while (reader.Read())
    {
        properties.Add(new Property
        {
            Id = reader.GetInt32(reader.GetOrdinal("Id")),
            Longitude = reader.IsDBNull(reader.GetOrdinal("Longitude")) ? null : (decimal?)reader.GetDecimal(reader.GetOrdinal("Longitude")),
            Latitude = reader.IsDBNull(reader.GetOrdinal("Latitude")) ? null : (decimal?)reader.GetDecimal(reader.GetOrdinal("Latitude"))
        });
    }
    queryResult.Properties = properties;

    // 移动到第二个结果集:媒体列表
    reader.NextResult();
    var mediaList = new List<Media>();
    while (reader.Read())
    {
        mediaList.Add(new Media
        {
            Id = reader.GetInt32(reader.GetOrdinal("Id")),
            Url = reader.GetString(reader.GetOrdinal("Url"))
        });
    }
    queryResult.RelatedMedia = mediaList;
}
finally
{
    if (dbConnection.State == System.Data.ConnectionState.Open)
        dbConnection.Close();
}
注意事项
  • 你当前存储过程第二个SELECT的逻辑有问题:WHERE PropertyId IN (SELECT Id FROM Property)会返回所有房产关联的媒体数据,而不是第一个查询里符合半径筛选条件的房产对应的媒体。建议先把筛选出的房产Id存入临时表,两个SELECT都关联临时表查询,避免返回多余数据。
  • 如果你不想手动写字段映射,EF Core 6+ 也可以通过翻译方法配合第三方扩展库实现自动多结果集映射,但手动用DataReader读取是零依赖、兼容性最好的方案,不会出现EF Core版本升级导致映射失效的问题。
  • 你之前在DbContext中定义的GetPropertiesProcedure这个DbSet可以直接删除,多结果集场景下不需要这个配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:39:25