我在C#中运行一个返回一个值(String)的SQL命令。我然后尝试将其保存到变量,但它总是抛出此异常:
System.Data.dll中发生了'System.InvalidOperationException'类型的第一次机会异常 线程''(0x1bbc)已退出,代码为0(0x0)。 System.InvalidOperationException:没有数据时读取的尝试无效。 在System.Data.SqlClient.SqlDataReader.GetValue(Int32 i)
但是,当我在SQL Server中运行相同的命令时,它肯定会输出一个值。
myCommand = new SqlCommand("SELECT TrialName FROM dbo.CT WHERE NumId='"+TrialId+"'", myConnection);
SqlDataReader dr = myCommand.ExecuteReader();
String TName = dr[0].ToString();
即使我对整个sqlcommand进行硬编码(而不是使用TrialId变量),它仍会抛出异常。这是怎么回事?
答案 0 :(得分:8)
在从数据阅读器读取之前,您必须先调用dr.Read():
myCommand = new SqlCommand("SELECT TrialName FROM dbo.CT WHERE NumId='"+TrialId+"'",
myConnection);
SqlDataReader dr = myCommand.ExecuteReader();
if(dr.Read())
{
String TName = dr[0].ToString();
}
SqlDataReader.Read()使读者前进到下一条记录,并在没有更多记录时返回false。
答案 1 :(得分:2)
正如其他答案所指出的,你需要在SqlDataReader上调用Read()方法。
但是,如果您只从select语句返回一个值,则应考虑使用SqlCommand.ExecuteScalar method。它不需要像使用SqlDataReader那样多的代码。
这样的事情:
string name = Convert.ToString(myCommand.ExecuteScalar());
答案 2 :(得分:1)
您需要先致电dr.Read()
才能阅读。 DataReader.Read()
将DataReader推进到下一行。您也必须在第一行调用它,以便可以在while循环中使用它:
while ( dr.Read() )
{
...
}
希望这有帮助!
答案 3 :(得分:0)
我可以建议使用参数化查询来帮助防范SQL注入漏洞吗?如果您需要ad-hoc SQL语句而不是存储过程,请考虑使用以下内容:
如果您只需要第一行的第一列值,则可以使用ExecuteScalar()
命令:
string TName;
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT TrialName FROM dbo.CT WHERE NumId=@Trial";
cmd.Parameters.AddWithValue("@Trial", TrialId);
TName = cmd.ExecuteScalar().ToString();
}
如果需要的值超过单个值,请继续使用SqlDataReader:
string TName;
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT TrialName FROM dbo.CT WHERE NumId=@Trial";
cmd.Parameters.AddWithValue("@Trial", TrialId);
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
TName = reader["TrialName"].ToString();
}
}
}