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

ASP.NET Core 3.1执行存储过程并将多结果集赋值给变量

解决ASP.NET Core 3.1中捕获存储过程多结果集的问题

要捕获存储过程返回的多个结果集,你需要使用ADO.NET原生的SqlDataReader来处理,因为EF Core 3.1的ExecuteSqlRaw/FromSqlRaw仅支持单结果集读取。以下是具体实现步骤:


1. 定义对应结果集的实体类

根据存储过程返回的三个结果集的字段,分别创建实体类(示例需根据实际字段调整):

// 第一个结果集的实体(对应CaseId、EpisodeId等字段)
public class CandidateInfo
{
    public int CaseId { get; set; }
    public int EpisodeId { get; set; }
    // 添加其他对应字段,如PatientName、DiagnosisDate等
}

// 第二个结果集的实体
public class SummaryStats
{
    public int TotalCandidates { get; set; }
    public decimal AverageScore { get; set; }
    // 添加其他对应字段
}

// 第三个结果集的实体
public class EligibilityRules
{
    public string RuleName { get; set; }
    public bool IsActive { get; set; }
    // 添加其他对应字段
}

2. 更新ViewModel结构

让你的ViewModel包含三个结果集的集合属性:

public class SpPotentialCandidatesForOncotypeDXViewModel
{
    public List<CandidateInfo> Candidates { get; set; }
    public List<SummaryStats> SummaryData { get; set; }
    public List<EligibilityRules> RuleData { get; set; }
}

3. 修改数据获取方法

通过DbContext获取数据库连接,使用SqlCommand和SqlDataReader依次读取三个结果集:

public SpPotentialCandidatesForOncotypeDXViewModel GetPotentialCandidatesForTheOncotypeDXData(DateTime startDate, DateTime endDate)
{
    var viewModel = new SpPotentialCandidatesForOncotypeDXViewModel();
    var dbConnection = _dbContext.Database.GetDbConnection();

    try
    {
        dbConnection.Open();

        // 创建存储过程命令
        using var command = dbConnection.CreateCommand();
        command.CommandText = "spPotentialCandidatesForOncotypeDX";
        command.CommandType = System.Data.CommandType.StoredProcedure;

        // 添加存储过程参数(参数名需与存储过程定义一致)
        var startParam = command.CreateParameter();
        startParam.ParameterName = "@startDate";
        startParam.Value = startDate;
        command.Parameters.Add(startParam);

        var endParam = command.CreateParameter();
        endParam.ParameterName = "@endDate";
        endParam.Value = endDate;
        command.Parameters.Add(endParam);

        // 执行命令获取数据阅读器
        using var reader = command.ExecuteReader();

        // 读取第一个结果集
        viewModel.Candidates = new List<CandidateInfo>();
        while (reader.Read())
        {
            var candidate = new CandidateInfo
            {
                CaseId = reader.GetInt32(reader.GetOrdinal("CaseId")),
                EpisodeId = reader.GetInt32(reader.GetOrdinal("EpisodeId")),
                // 处理可能为null的字段:先判断是否为DBNull再赋值
                // PatientName = reader.IsDBNull(reader.GetOrdinal("PatientName")) ? null : reader.GetString(reader.GetOrdinal("PatientName"))
            };
            viewModel.Candidates.Add(candidate);
        }

        // 切换到第二个结果集
        reader.NextResult();
        viewModel.SummaryData = new List<SummaryStats>();
        while (reader.Read())
        {
            var stats = new SummaryStats
            {
                TotalCandidates = reader.GetInt32(reader.GetOrdinal("TotalCandidates")),
                AverageScore = reader.GetDecimal(reader.GetOrdinal("AverageScore"))
            };
            viewModel.SummaryData.Add(stats);
        }

        // 切换到第三个结果集
        reader.NextResult();
        viewModel.RuleData = new List<EligibilityRules>();
        while (reader.Read())
        {
            var rule = new EligibilityRules
            {
                RuleName = reader.GetString(reader.GetOrdinal("RuleName")),
                IsActive = reader.GetBoolean(reader.GetOrdinal("IsActive"))
            };
            viewModel.RuleData.Add(rule);
        }
    }
    catch (Exception ex)
    {
        AppLog.WriteError("GetPotentialCandidatesForTheOncotypeDXData", ex.Message);
    }
    finally
    {
        // 确保连接关闭
        if (dbConnection.State == System.Data.ConnectionState.Open)
        {
            dbConnection.Close();
        }
    }

    return viewModel;
}

4. 在视图中使用结果集

通过ViewModel遍历各个结果集输出:

@model SpPotentialCandidatesForOncotypeDXViewModel

<h2>候选患者列表</h2>
<table class="table">
    <thead>
        <tr>
            <th>Case ID</th>
            <th>Episode ID</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var candidate in Model.Candidates)
        {
            <tr>
                <td>@candidate.CaseId</td>
                <td>@candidate.EpisodeId</td>
            </tr>
        }
    </tbody>
</table>

<h2>统计数据</h2>
@foreach (var stats in Model.SummaryData)
{
    <p>总候选人数:@stats.TotalCandidates,平均评分:@stats.AverageScore</p>
}

<h2> eligibility规则</h2>
<ul>
    @foreach (var rule in Model.RuleData)
    {
        <li>@rule.RuleName:@(rule.IsActive ? "启用" : "禁用")</li>
    }
</ul>

关键注意事项

  • 参数名必须与存储过程中定义的参数名完全一致,避免使用@p0这类占位符,防止参数匹配错误。
  • 读取字段时,使用GetOrdinal获取列索引比直接用列名更安全,可避免大小写或列名顺序变化导致的错误。
  • 处理可空字段时,需先通过reader.IsDBNull()判断,再进行赋值,避免抛出空值异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:37:39