Sql server SqlDataReader.Read是否不按广告的方式工作?

Sql server SqlDataReader.Read是否不按广告的方式工作?,sql-server,ado.net,sqldatareader,Sql Server,Ado.net,Sqldatareader,所以我在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(); S

所以我在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()的调用来获取数据,但是:这种行为与明确表示“SqlDataReader的默认位置在第一条记录之前。因此,必须调用Read才能开始访问任何数据”的相反。这也与我在web上发现的SqlDataReader用法的每一个例子相反,比如它似乎只是为了嘲弄我而存在

请注意,我已经针对.NET3.5和.NET4.5测试了代码,结果相同

我错过什么了吗?ADO.NET中有错误吗?欢迎您的任何意见

更新1: 我在最后一行得到的实际例外是:

System.Data.dll中发生类型为“System.InvalidOperationException”的未处理异常

其他信息:当不存在数据时,尝试读取无效

更新2:


因为Nathan Skerl无法重现这种行为,并且发布了经过验证的工作代码,但随后对我来说失败了,所以我怀疑我们运行的平台可能存在问题。作为记录,我使用的是Windows7 Professional(64位)Service Pack 1,并根据.NETFramework 3.5和4.5编译了我的项目,结果相同。如果我没有包含任何相关信息,请让我知道,我会添加它。

更新:经过一些故障排除,我们通过扩展结果视图(调用
Read()
并使用行)在调试器中检查读卡器,发现读卡器是空的

使用您的代码,我在Linqpad中运行了这个单元测试,结果与预期的一样,最初的reader.read()前进到第“1”行,第二次调用前进到第“2”行。您能否通过以下测试重现错误:

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行时遇到了完全相同的问题,该行是从Microsoft Dynamics 2013R2中使用ADO SQLCommand调用的SP返回的

具体而言,我使用此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附件,它将给我一条消息,其中包含来自SP结果集的第1行第1列的数据

对于IF和.Read(),它将给出一个错误,指出在不存在数据的情况下发出了读取数据的命令。它是指消息前的代码行

SQLReader.Item('QtyCumulative');
如本期所述,这与文档中明确指出的.ExecuteReader()SQLReader集合保留在执行后数据开始之前的行相矛盾

这肯定不会发生,最重要的是,如果我们在调用.ExecuteReader()之后立即调用SQLReader对象的.Read()方法,那么它将移动到结果集的第二行


显然,它们与SqlDataReader对象有关。

您在最后一行收到的实际异常是什么?编辑问题以包含实际异常。我将您的代码直接复制/粘贴到我的方法中,而不是我自己的代码。我更改了第二行以获得实际连接,并注释掉了a.Dump()和b.Dump行,以便编译。我在问题中描述的行为再次发生。也就是说,行字符串a=(String)rdr[“a”];抛出与我之前遇到的相同的异常。因为我的代码在您的系统上工作,所以我相信可能会有一些关于该平台的有趣业务。我将更新我的问题,以指示我正在使用的所有内容的版本。经过一段时间的思考后,我认为如果是SqlDataReader从第一行开始而不是在第一行之前开始的问题,则会在字符串b的赋值上引发异常,而不是字符串a的赋值上引发异常。。。我将指出,在第一个rdr.Read调用之前进行调试时,我检查了rdr,两行都出现在ResultsView成员中,然后在第一个rdr.Read调用之后,ResultsView成员为空…非常奇怪。我能够重新设置错误的唯一方法是通过调用.Read()多行来耗尽数据,或者强制关闭连接。你能试试上面添加的第二种图案吗?我不知道奇怪之处是否在调试器中,而不是你的代码中,也就是说,在分配调用时,你在resultsview中看到的数据实际上不在那里?关于调试器,我和你的想法是一样的。。。当我停止检查rdr的值时,最奇怪的部分就消失了。具体地说,如果我在第一次调用Read()之前检查rdr的ResultsView,那么在调用Read()之后出现的任何行都会消失。我运行了两个测试,得到了表的全部内容(两次运行中所有的代码和数据库表都是相同的),第一次检查了rdr的ResultView,第二次没有检查。第一个测试结果是Read()之后所有结果都消失了,第二个结果是除了第一行之外所有的行都在那里。对于那些容易做到这一点的人,他们可以在结果集的最顶端选择一些值,只需“生成”一行数据,然后将这一行与实际结果集合并。这就是我绕过第0行的问题所做的。