检查 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);
}
感谢您提出宝贵建议。
请看我下面的代码,我正在尝试从 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);
}
感谢您提出宝贵建议。