从 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 链接!我过去使用过SqlDataReader
s,我认为需要维护很多代码。然后我尝试了DataTables
并认为它们要快得多。将来编写其他代码时,我将不得不牢记替代方案!再次感谢分享!
这就是我们所说的完美解决方案【参考方案3】:
您可以使用 if (dr.NextResult())
然后用 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 中具有多个记录集的存储过程
Apache DbUtils:处理从存储过程返回的多个结果集