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

C#读取SQL Server存储过程多结果集拆分至列表与ViewBag方法

解决方案

针对当前场景的直接实现

你原有代码的问题是误用了Read()方法——这个方法是用来遍历单个结果集内的行的,读取多个结果集需要调用SqlDataReader的NextResult()方法逐一切换结果集,不需要逐行手动写映射,直接用DataTable.Load()就能把当前结果集的全部数据灌入对应DataTable。
修正后的代码片段:

public void financeData(int id, string purchase_number)
{
    // 数据库连接务必用using包裹,自动释放资源,避免连接泄漏
    using (SqlConnection con = new SqlConnection(constr))
    {
        string query = "getData";
        using (SqlCommand command = new SqlCommand(query, con))
        {
            command.CommandType = CommandType.StoredProcedure;
            // 建议显式指定参数类型,AddWithValue在部分场景下会因为类型推断错误导致索引失效
            command.Parameters.Add("@id", SqlDbType.Int).Value = id;
            command.Parameters.Add("@purchase_number", SqlDbType.NVarChar, 50).Value = purchase_number;

            DataTable top_purchases = new DataTable();
            DataTable transaction_summary = new DataTable();
            DataTable maximum_amount = new DataTable();

            con.Open();
            using (SqlDataReader reader = command.ExecuteReader())
            {
                // 加载第一个结果集
                top_purchases.Load(reader);
                // 切换到第二个结果集
                reader.NextResult();
                transaction_summary.Load(reader);
                // 切换到第三个结果集
                reader.NextResult();
                maximum_amount.Load(reader);
            }
        }
    }

    // 后续直接把三个DataTable赋值给ViewBag/ViewData即可
    // ViewBag.TopPurchases = top_purchases;
    // ViewBag.TransactionSummary = transaction_summary;
    // ViewBag.MaximumAmount = maximum_amount;
}

注意:结果集的读取顺序必须和存储过程里SELECT语句的编写顺序完全一致,否则会出现数据错位。

通用封装方案(适配所有多结果集存储过程)

如果后续要新增大量同类存储过程,完全可以把多结果集读取的逻辑封装成通用方法,不用每次重复写ADO.NET的模板代码。下面是可直接复用的封装:

第一步:封装通用多结果集读取方法

/// <summary>
/// 执行存储过程,返回多个结果集
/// </summary>
/// <param name="connectionString">数据库连接字符串</param>
/// <param name="storedProcedureName">存储过程名</param>
/// <param name="parameters">存储过程参数,键为参数名,值为参数值</param>
/// <returns>按存储过程SELECT顺序返回的DataTable列表</returns>
public static List<DataTable> ExecuteStoredProcedureWithMultipleResults(string connectionString, string storedProcedureName, Dictionary<string, object> parameters = null)
{
    List<DataTable> resultTables = new List<DataTable>();
    using (SqlConnection con = new SqlConnection(connectionString))
    {
        using (SqlCommand cmd = new SqlCommand(storedProcedureName, con))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            // 自动追加参数
            if (parameters != null)
            {
                foreach (var param in parameters)
                {
                    cmd.Parameters.AddWithValue(param.Key, param.Value ?? DBNull.Value);
                }
            }
            con.Open();
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                // 循环读取所有结果集,直到没有下一个结果为止
                do
                {
                    DataTable dt = new DataTable();
                    dt.Load(reader);
                    resultTables.Add(dt);
                } while (reader.NextResult());
            }
        }
    }
    return resultTables;
}

第二步:业务代码直接调用

原来的财务数据读取逻辑可以简化成几行代码:

public void financeData(int id, string purchase_number)
{
    var parameters = new Dictionary<string, object>
    {
        {"@id", id},
        {"@purchase_number", purchase_number}
    };
    List<DataTable> results = ExecuteStoredProcedureWithMultipleResults(constr, "getData", parameters);
    
    // 按索引取对应结果集即可,索引从0开始,对应存储过程里第1个SELECT的结果
    DataTable top_purchases = results[0];
    DataTable transaction_summary = results[1];
    DataTable maximum_amount = results[2];

    // 后续赋值ViewBag逻辑不变
}

可选扩展

如果不想用弱类型的DataTable,还可以在通用方法基础上追加扩展,支持把结果集直接映射到指定的强类型List<T>,适配需要强类型处理的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:01:11