我知道通常建议的从存储过程填充DataSet实例的方法是使用SqlDataAdapter.Fill(DataSet).我能找到的每个答案都说它以开箱即用的方式使用它.我通常会批准它,效果很好.
但是,当您需要在存储过程输出和DataSet输入之间处理数据时,它会崩溃.具体来说,在输出中使用自定义CLR类型时,它会因InvalidOperationException而中断:DataReader.GetFieldType(n)返回null.其中n是列的列索引(在其中一个表中;似乎没有明显的方法来告知列索引引用哪个表)在其输出中使用CLR类型.这是可以理解的,因为读者不知道相关列中的数据类型.
我可以打破CLR类型的反序列化逻辑并在两个地方使用它,但我似乎没有时间在Fill()分解之前调用任何这样的反序列化方法.
我知道SqlCommand.ExecuteReader(),但似乎只能得到一个表.
有问题的CLR类型旨在用一些更严格的内容替换其中一个核心系统字段(目前存储为自由格式文本).已经讨论了通过数据库并向这样一个字段的每个返回实例添加方法调用的问题作为一种可能性,但肯定是一项非常重要的工作量.因此,人们认为转换可以在DAL中完成(只需要以编程方式识别这些列,这是可行的),使存储对客户端透明,客户端使用对数据库仍然透明的数据.
因此:如何在不使用SqlDataAdapter.Fill()的情况下访问存储过程输出中的所有表?或者,如何挂钩执行SqlDataAdapter.Fill()以在执行SP和填充DataSet之间进行手动处理?
最佳答案 您可以使用DataReader选择多个表.您可以使用
reader.NextResult
检查是否有更多结果集并将数据读取器推进到它:
using (var con = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
using (var cmd = new SqlCommand("StoredProcedureName", con))
{
cmd.CommandType = CommandType.StoredProcedure;
int rowCount = 0;
con.Open();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
Console.WriteLine("Object 1 in Row {0}: '{1}'", ++rowCount, rdr[0]);
}
if (rdr.NextResult())
{
rowCount = 0;
while (rdr.Read())
{
Console.WriteLine("Object 1 in Row {0}: '{1}'", ++rowCount, rdr[0]);
}
}
}
}
}