从 C# 中的存储过程返回多个记录集

Posted

技术标签:

【中文标题】从 C# 中的存储过程返回多个记录集【英文标题】:Return multiple recordsets from stored proc in C# 【发布时间】:2013-09-01 21:13:23 【问题描述】:

我必须将 ASP 经典系统转换为 C#

我有一个存储过程,最多可以返回 7 个记录集(取决于传入的参数)。

我需要知道如何简单地将所有记录集作为单独的 DataTables 返回,这样我就可以遍历所有的数据表,当我到达它的末尾时跳到下一个 DataTable,而不必运行多个 SQL 语句并使用多个适配器。填充语句将每个表添加到数据集中。

在经典中,当我到达循环末尾以移至下一条语句时,这是一个简单的 Do While not objRS.EOF 循环,带有 objRS.NextRecordset()。

有什么我可以使用而不需要完全重写当前后端代码的东西吗?

每个记录集都有不同数量的列和行。它们彼此无关。我们从存储过程中返回多个记录集以减少流量。

例子会很好。

谢谢

【问题讨论】:

【参考方案1】:

这将返回你所需要的一切

using (SqlConnection conn = new System.Data.SqlClient.SqlConnection(connString))

    using (SqlCommand cmd = new SqlCommand())
    
        cmd.CommandText = "yoursp";
        cmd.Connection = conn;
        cmd.CommandType = CommandType.StoredProcedure;

        conn.Open();

        SqlDataAdapter adapter = new SqlDataAdapter(cmd);

        DataSet ds = new DataSet();
        adapter.Fill(ds);

        conn.Close();
    

【讨论】:

这是我用来从存储过程中获取多个记录集的方法。为了澄清起见,记录集存储在ds.Tables 中,您可能希望将DataSet ds = new DataSet(); 放在开头,以便可以在using (SqlConnection conn = new System.Data.SqlClient.SqlConnection(connString)) 块之外引用它。只是一个想法。 是的,您可以将其移出。只是举一个例子来说明如何做到这一点;。【参考方案2】:

如果您使用SqlDataAdapter.Fill() 方法填充数据集,那么从存储过程返回的每个记录集都将作为数据集中的数据表返回

DataSet dataset = new DataSet();
using (var adapter = new SqlDataAdapter("yourStoredProcedure", yourConnectionString))

    adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
    adapter.Fill(dataset);

for (int i = 0; i < dataset.Tables.Count; i++)

    // Do something for each recordset

如果您使用 SqlDataReader 则可以使用 SqlDataReader.NextResult() 方法前进到下一个记录集:

using (var connection = new SqlConnection(yourConnectionString))
using (var command = new SqlCommand("yourStoredProcedure"))

    connection.Open();
    using (var reader = command.ExecuteReader())
    
        while (reader.Read())
        
            // do something with first result set;
        
        if (reader.NextResult())
        
            while (reader.Read())
            
                // do something with second result set;
            
        
        else
        
            return;
        
        if (reader.NextResult())
        
            while (reader.Read())
            
                // do something with third result set;
            
        
        else
        
            return;
        
    

【讨论】:

我从来不知道你可以使用SqlDataReader.ExecuteReader().NextResult() 获得多个结果集。感谢您的详细回答! 确实可以,我通常更喜欢使用 SqlDataReader,因为它只存储当前记录,而不用担心已经读取的内容和尚未读取的内容,从而降低了内存使用率。然而,this answer 将数据集与数据读取器进行比较有一个很好的类比。 感谢分享 SO 链接!我过去使用过SqlDataReaders,我认为需要维护很多代码。然后我尝试了DataTables 并认为它们要快得多。将来编写其他代码时,我将不得不牢记替代方案!再次感谢分享! 这就是我们所说的完美解决方案【参考方案3】:

您可以使用 if (dr.NextResult())

来检查 dr 是否有更多记录集 ot no

然后用 dr.read 再次循环

试试这个

string connStr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
SqlConnection Con = new SqlConnection(connStr);

try

    string str1 = "select productid,productname from products;select VendorFName from vendor";
    SqlCommand com = new SqlCommand(str1, Con);

    com.Connection.Open();

    SqlDataReader dr = com.ExecuteReader();

    DropDownList1.Items.Add("Select Product Id");
    DropDownList2.Items.Add("Select Vendor Name");

    while(dr.Read())
    
        DropDownList1.Items.Add(dr.GetValue(0).ToString());
    

    if (dr.NextResult())
    
        while (dr.Read())
        
            DropDownList2.Items.Add(dr.GetValue(0).ToString());
        
    

catch (Exception ex)


finally

    if (Con.State == ConnectionState.Open)
    
        Con.Close();
    

【讨论】:

【参考方案4】:
SqlConnection con=new SqlConnection("YourConnection String");
SqlCommand cmd=new SqlCommand();
SqlDataAdapter da=new SqlDataAdapter();
DataSet ds = new DataSet();
cmd = new SqlCommand("name of your Stored Procedure", con);
cmd.CommandType = CommandType.StoredProcedure;
//cmd.Parameters.AddWithValue("@SuperID", id);//if you have parameters.
da = new SqlDataAdapter(cmd);
da.Fill(ds);
con.Close();

在此之后,您可以利用不同的 (7) 记录集使用

ds.Tables[0]
ds.Tables[1]
ds.Tables[2]
ds.Tables[3]
ds.Tables[4]
ds.Tables[5]
ds.Tables[6]

【讨论】:

谢谢,我喜欢这个答案纯粹是因为我已经有一个带有包装函数的数据类,可以处理连接并在类被销毁时处理它们等。我只是想使用我拥有的现有函数并引用数据集中的表格。

以上是关于从 C# 中的存储过程返回多个记录集的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 6 中具有多个记录集的存储过程

C#调用Oracle带输出数据集的存储过程

Apache DbUtils:处理从存储过程返回的多个结果集

c#中两种不同的存储过程调用与比较

C# 通过DataSet 获取SQL 存储过程返回的多个结果集(tables)

Asp.net(C#) 获取 执行sql server 语句/存储过程后的 多个返回值?