检查 Datareader 是否为空

check Datareader is null or not

请看我下面的代码,我正在尝试从 table 中读取数据,如果 table 中有任何行符合条件,则执行一些代码行,如果有没有行然后执行其他代码集。

当我执行这段代码时,它抛出了一个异常。 "Invalid attempt to read when no data is present" 关于到底哪里出了问题的任何建议。

public void Check_Last_RegNo()
    {
        try
        {

            con = new SqlConnection(cs.DBConn);
            con.Open();
            string ct = "SELECT Max(RegistrationNo) from tbl_StudentRegNo where (RegistrationNo Like'%" + label3.Text + "%')";
            cmd = new SqlCommand(ct);
            cmd.Connection = con;
            rdr = cmd.ExecuteReader();
            if (rdr[0]!=null && rdr[0]!=DBNull.Value)
            {

                int ii = 1;
                for (int max = 0; max < dataGridView1.Rows.Count; max++)
                {

                    label4.Text = ii.ToString("0000");
                    string concati = reg_no + label3.Text + label4.Text;
                    dataGridView1.Rows[max].Cells[2].Value = concati;
                    ii++;
                }


            }
            else
                {
                    while (rdr.HasRows)
                    {
                        label5.Text = (rdr[0]).ToString();
                        string lastregno = label5.Text;
                        string digits = lastregno.Substring(lastregno.Length - 4, 4);
                        label4.Text = digits.ToString();
                        int i = Convert.ToInt32(digits) + 1;
                        for (int max = 0; max < dataGridView1.Rows.Count; max++)
                        {

                            label4.Text = i.ToString("0000");
                            string concati = reg_no + label3.Text + label4.Text;
                            dataGridView1.Rows[max].Cells[2].Value = concati;
                            i++;
                        }
                    }
                }


        con.Close();

        }

        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

您正在尝试检查 reader 值,但没有使用 if 语句验证它是否有任何行。这会导致异常。

您可以使用 reader.Read() 检查并在一个操作中将 reader 移动到下一行。

如果您需要检查 reader 是否有执行备用流程的行,请检查 rdr.HasRows 作为第一个条件。

if (rdr.HasRows) 
{
            while(rdr.Read())
            {
                label5.Text = (rdr[0]).ToString();
                string lastregno = label5.Text;
                string digits = lastregno.Substring(lastregno.Length - 4, 4);
                label4.Text = digits.ToString();
                int i = Convert.ToInt32(digits) + 1;
                for (int max = 0; max < dataGridView1.Rows.Count; max++)
                {

                    label4.Text = i.ToString("0000");
                    string concati = reg_no + label3.Text + label4.Text;
                    dataGridView1.Rows[max].Cells[2].Value = concati;
                    i++;
                }
            }
}
else
            {
                int ii = 1;
                for (int max = 0; max < dataGridView1.Rows.Count; max++)
                {

                    label4.Text = ii.ToString("0000");
                    string concati = reg_no + label3.Text + label4.Text;
                    dataGridView1.Rows[max].Cells[2].Value = concati;
                    ii++;
                }
            }

你的第一个 if 语句没有意义。您可以使用 if 条件检查是否找到任何行并逐行读取,并且必须检查 rdr[0] 是否不为 null 然后对其进行操作。 :

if (rdr.HasRows)  // check if any row found
        {
            while(rdr.Read())  // read all matched rows one by one
            {
                label5.Text = rdr[0] != DbNull.Value ? (rdr[0]).ToString() : string.Empty;
                string lastregno = label5.Text;
                string digits = lastregno.Substring(lastregno.Length - 4, 4);
                label4.Text = digits.ToString();
                int i = Convert.ToInt32(digits) + 1;
                for (int max = 0; max < dataGridView1.Rows.Count; max++)
                {

                    label4.Text = i.ToString("0000");
                    string concati = reg_no + label3.Text + label4.Text;
                    dataGridView1.Rows[max].Cells[2].Value = concati;
                    i++;
                }
            }
        }

SqlDataReader 逐行读取一行,所以要读取一行我们必须调用 rdr.Read(),当我们调用它时,它会读取一行,所以写 while(rdr.Read()) 我们说的是一条一条读取记录,直到处理完所有记录。

当你先调用 rdr[0] 而没有调用 rdr.Read() 时,它显然会失败,因为没有正在读取的行 rdr 保留。

当您使用 ExecuteReader 构建 SqlDataReader 时,返回的对象不位于返回数据集(如果有)的第一条记录上,因此,在尝试访问reader,你需要调用 Read()HasRows 后者,如果你只想知道是否有记录,第一个,如果你需要实际读取返回的数据集。您的错误是由于您在第一条记录上移动 Reader 之前尝试使用 Reader 访问 rdr[0] 而触发的。

但是你让事情复杂化了,因为,给出这个查询:

string ct = "SELECT Max(RegistrationNo) ....";

然后你有一个空的或只有一列的一行。 所以这里最好的调用方法是ExecuteScalar

 cmd = new SqlCommand(ct);
 cmd.Connection = con;
 object result = cmd.ExecuteScalar();
 if(result != null)
 {
    // Now you have here your registration value as a string
    string maxRegistrationNo = result.ToString();

    // You could apply your logic to extract the required parts
    ....
    ....
 }
 else
 {
     // Your logic for a null return from your query
     ......
 }

您可以从 MSDN 中了解到

Use the ExecuteScalar method to retrieve a single value (for example, an aggregate value) from a database. This requires less code than using the ExecuteReader method, and then performing the operations that you need to generate the single value using the data returned by a SqlDataReader.

最后我不得不稍微更改一下我的代码,异常消失了,更改似乎有点复杂但它起作用了。这是代码。

try
        {

            con = new SqlConnection(cs.DBConn);
            con.Open();
            string ct = "SELECT Max(RegistrationNo) from tbl_StudentRegNo where (RegistrationNo Like'%" + lblshortcode.Text + "%')";
            cmd = new SqlCommand(ct);
            cmd.Connection = con;
            rdr = cmd.ExecuteReader();
            if (rdr.HasRows)
            {
                while (rdr.Read())
                {
                    lbllastregno.Text = (rdr[0]).ToString();
                    string lastregno = lbllastregno.Text;
                    if(rdr[0]!=DBNull.Value)
                    {
                        string current_serial_no = lastregno.Substring(lastregno.Length - 4, 4);
                        lblcurrentsno.Text = current_serial_no;
                        int next_serial_no = Convert.ToInt32(current_serial_no) + 1;
                        lblnextsno.Text = next_serial_no.ToString("0000");
                    }
                    else
                    {
                        lbllastregno.Text = reg_no + lblshortcode.Text + lbldigitformat.Text;
                    }

                }
            }
            else
            {
                lbllastregno.Text = reg_no + lblshortcode.Text + lbldigitformat.Text;
            }
            con.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

感谢您提出宝贵建议。