SqlDataReader 不存在数据时尝试读取无效

Invalid attempt to read when no data is present by SqlDataReader

这是我的代码

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        SqlConnection con = new SqlConnection(@"Data Source=.;Initial Catalog=DayanaP;Integrated Security=True");
        
        private void button1_Click(object sender, EventArgs e)
        {
            con.Open();
            SqlCommand test = new SqlCommand("select * from maindata where userid='"+textBox1.Text+ "' and password='" + textBox2.Text + "' ", con);
            SqlDataReader dr = test.ExecuteReader();
            int count = 0;
            while (dr.Read())
            {
                count++;
            }
            if (count == 1)
                MessageBox.Show(dr.GetString(0));
            else
            {
                MessageBox.Show("123");
            }

            con.Close();
        }
    }
}

那是我在代码中使用的数据库主表

当我输入用户名和密码时,我希望看到一个显示用户名字的消息框,但我收到此错误:

An unhandled exception of type 'System.InvalidOperationException' 
occurred in System.Data.dll
Additional information: Invalid attempt to read when no data is present.

我该如何解决这个问题?

dr.Read() 读取下一个可用行(如果有)。如果没有更多的行,dr.Read() returns false.

所以在你的代码中:

 while (dr.Read())
 {
      count++;
 }

你调用 dr.Read() 直到它 returns false 意味着 没有更多可读的内容
因此,您对 dr.GetString(0) 的调用出现在所有内容都已阅读之后。

一个解决方案可能如下所示:

string s = null;
if (dr.Read()) s = dr.GetString(0);
if (string.IsNullOrEmpty(s) || dr.Read())
    MessageBox.Show("123");
else
    MessageBox.Show(s);

这与(我猜)您的代码打算执行的操作相同:如果结果集中只有一行,则显示返回的字符串。


但是你的代码问题比较多:

  1. 不要将用户输入直接插入到您的查询中!您的代码对 SQL Injection 开放。请使用参数化查询。
  2. 而不是 SELECT * 我建议明确命名要获取的列。你怎么知道第 0 列就是你想要的字符串?
  3. 因为您只想要名字,所以使用 SELECT firstname... 可能更好,使用 ExecuteScalar() 而不是 ExecuteReader()。但您可能希望稍后在您的项目中添加更多专栏。

您应该首先检查数据读取器是否有像这个例子那样的行。您还希望确保从 while 块内的数据读取器检索值。

 var value = string.empty;
 if(dr.HasRows)
 {    
     while (dr.Read())
     {
        count++;
        value = dr.GetString(0);
     }    
 }

您已经消费了 reader

    while (dr.Read())
    {
        count++;
    }
    //dr is now empty
    if (count == 1)
        MessageBox.Show(dr.GetString(0));

这就是你需要的

    while (dr.Read())
    {
        count++;
        if (count == 1)
            MessageBox.Show(dr.GetString(0));
    }

或更短

    if (dr.Read())
    {
        MessageBox.Show(dr.GetString(0));
    }
    else
    {
        MessageBox.Show("123");
    }

    string rdrZero = "123";
    if (dr.Read())
    {
        rdrZero = GetString(0));
    }
    MessageBox.Show(rdrZero);