所以我在ADO中运行查询。NET,我知道返回单行。我的代码的相关部分如下:
SqlCommand sqc = new SqlCommand();
sqc.Connection = new SqlConnection("connection string");
sqc.CommandText = "SELECT A, B FROM C WHERE D=@d";
sqc.Parameters.AddWithValue("@d", "d");
sqc.Connection.Open();
SqlDataReader rdr = sqc.ExecuteReader();
bool boolio = rdr.Read();
String a = (String)rdr["A"];
当我运行这个时,我在最后一行得到一个异常,抱怨我试图读取没有数据的地方。
当我在VS中完成这个步骤时,我在rdr. read()行执行之前检查rdr,我可以看到我想要的数据位于读取器中。然后我调用rdr.Read(),结果是FALSE,表示没有更多的数据可供我读取。当我再次检查rdr时,内部ResultsView是空的。
我意识到我可以简单地通过丢弃对Read()的调用来获得我的数据,但是:这种行为与MSDN文档相反,该文档明确地说"SqlDataReader的默认位置在第一条记录之前。因此,你必须调用Read来开始访问任何数据。这也与我在网上发现的SqlDataReader使用的每个例子相反,比如这个问题,它的存在似乎只是为了嘲弄我。
请注意,我已经在。net 3.5和。net 4.5上测试了我的代码,结果相同。
我错过了什么吗?ADO.NET中有bug吗?任何输入是感激的!
更新1:我在最后一行得到的实际异常是:
更新2:类型为"System"的未处理异常。InvalidOperationException'在System.Data.dll中发生
附加信息:当没有数据存在时,尝试读取无效。
因为Nathan Skerl无法重现这种行为,并且发布了经过验证的工作代码,但随后对我来说失败了,我怀疑可能是我们运行的平台有问题。根据记录,我使用的是Windows 7 Professional(64位)Service Pack 1,并针对。net Framework 3.5和4.5编译了我的项目,结果相同。
UPDATE:经过一些故障排除后,我们意识到阅读器是空的,因为通过扩展Results View(调用Read()
并消耗行)在调试器中检查阅读器。
使用您的代码,我在Linqpad中运行了这个单元测试,结果如预期的那样,初始的reader.read()前进到行"ONE",第二次调用行"TWO"。您可以用这样的测试重现错误吗?
SqlCommand sqc = new SqlCommand();
sqc.Connection = (SqlConnection)this.Connection;
sqc.CommandText = "SELECT 'ONE' [A] union all select 'TWO' order by [A] asc;";
sqc.Parameters.AddWithValue("@d", "d");
sqc.Connection.Open();
SqlDataReader rdr = sqc.ExecuteReader();
bool boolio = rdr.Read();
String a = (String)rdr["A"];
a.Dump();
rdr.Read();
String b = (String)rdr["A"];
b.Dump();
你能告诉我们这个模式返回什么吗?
using (SqlConnection connection = (SqlConnection)this.Connection)
using (SqlCommand sqc = new SqlCommand("select 'ONE' as [A] union all select 'TWO';", connection))
{
connection.Open();
using (SqlDataReader rdr = sqc.ExecuteReader())
{
while (rdr.Read())
{
Console.WriteLine(String.Format("{0}", (String)rdr["A"]));
}
}
}
我遇到了完全相同的问题,试图读取1行,从SP返回,称为使用Microsoft Dynamics 2013R2的ADO SQLCommand。
具体来说,我使用这个C/AL代码来调用我的SP:
SQLCommand := SQLCommand.SqlCommand();
SQLCommand.CommandText := 'Custom_Item_Card_report_Get_Item_Qties'; //name of SP
SQLCommand.Connection := SQLConnection;
SQLCommand.CommandType := SQLCommand.CommandType.StoredProcedure;
SQLCommand.CommandTimeout := 0;
IF SQLCommand.Parameters.Count = 0 THEN BEGIN
SQLCommand.Parameters.AddWithValue('@CompanyName', COMPANYNAME);
SQLCommand.Parameters.AddWithValue('@ItemNo', InputItemCode);
SQLCommand.Parameters.AddWithValue('@FromDate', InputDateFrom);
SQLCommand.Parameters.AddWithValue('@Location', InputLocation);
END;
SQLReader := SQLCommand.ExecuteReader;
//IF SQLReader.Read() THEN BEGIN
rs1QtyCumulative := SQLReader.Item('QtyCumulative');
MESSAGE(FORMAT(rs1QtyCumulative));
//END;
现在,在我的结果集中,我只有2行(按3列小数)。第0行和第1行,我们叫它们
如本问题所述,如果没有IF附件,它将给我来自第1行,第1列的数据的消息来自SP的结果集。
使用 IF和. read(),它将给出一个错误,说明在不存在的情况下发出了读取数据的命令。它指的是MESSAGE之前的那行代码。
SQLReader.Item('QtyCumulative');
这与文档中明确指出的. executereader ()将在执行后将SQLReader集合指向数据开始之前的行相矛盾。
这种肯定不会发生,最重要的是,如果我们为SQLReader对象调用. read ()方法,在调用. executereader()之后,它将移动到结果集的第二行。
显然他们有一些调试与SqlDataReader对象。