我有一个具有自动完成模式的文本框,其值表示为项目条形码,我想检查一下如果这个条形码确实存在于数据库中,那么附上与该条形码相关的项目名称,当我输入无效的条形码,它给这个捕获消息和textBox被清除,但另一方面,即使我输入有效或自动完成值,它会在每次正确的尝试中一次又一次地显示聊天消息!
private void sBillItemBartxt_Leave(object sender, EventArgs e)
{
try
{
if (sBillItemBartxt.Text.Trim() != "")
{
cn.Open();
SqlCommand cmd = new SqlCommand("select itmBar from item", cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dtl = new DataTable();
da.Fill(dtl);
if (dtl.Rows.Count > 0)
{
cmd = new SqlCommand("select itmName from item where itmBar ='" + sBillItemBartxt.Text + "' ", cn);
dr = cmd.ExecuteReader();
dr.Read();
sBillItemNametxt.Text = dr["itmName"].ToString();
dr.Close();
sBillItemNametxt.ReadOnly = true;
cn.Close();
bindExDateGrid();
}
}
}
catch
{
MessageBox.Show("Please enter a valid item barcode");
sBillItemBartxt.Text = "";
sBillItemBartxt.Focus();
}
}
答案 0 :(得分:1)
正如@EBrown所说,在调用dr.Read();
之前,你没有检查是否有任何与条形码相匹配的记录
cmd = new SqlCommand("select itmName from item where itmBar ='" + sBillItemBartxt.Text + "' ", cn);
dr = cmd.ExecuteReader();
if(dr.HasRows)
{
dr.Read();
sBillItemNametxt.Text = dr["itmName"].ToString();
dr.Close();
sBillItemNametxt.ReadOnly = true;
cn.Close();
bindExDateGrid();
}
上面的代码应该有希望停止你收到的评论错误。
@Plutonix SqlException类中的消息表示当没有数据表示时无效的读取尝试 - Mouad Raizada
同样@Plutonix @rach指出你应该使用参数化的sql查询,这在下面的代码中有说明。
cmd = new SqlCommand("select itmName from item where itmBar = @barcode", cn);
cmd.Parameters.Add(new SqlParameter("@barcode", sBillItemBartxt.Text.Trim()));
dr = cmd.ExecuteReader();
if(dr.HasRows)
{
dr.Read();
sBillItemNametxt.Text = dr["itmName"].ToString();
dr.Close();
sBillItemNametxt.ReadOnly = true;
cn.Close();
bindExDateGrid();
}
我还注意到,每次扫描条形码时,都会将数据库中的所有条形码加载到应用程序中,然后对其进行过滤,这应该是数据库的工作而不是应用程序。
SqlCommand cmd = new SqlCommand("select itmBar from item", cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dtl = new DataTable();
da.Fill(dtl);
if (dtl.Rows.Count > 0)
{
我可以看到,这可能会成为未来可能出现的问题,因为随着条形码数量的增加,从数据库中检索数据的时间也是如此,如果打算在网络上使用,添加的客户端数量越多,数据通过网络传输。因此,数据库应仅返回允许应用程序继续所需的数据。
一些代码整洁的评论
// Checking to see if the sBillItemBartxt.Text is not empty.
if (!string.IsNullOrWhiteSpace(sBillItemBartxt.Text))
{
try
{
// the using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object.
using (cn)
{
// Checking to see if the connection to the Database is all ready open.
if (cn.State != ConnectionState.Open)
{
cn.Open();
}
// Building the SQL Query.
SqlCommand cmd = new SqlCommand("SELECT itmName, itmBar from item where itmBar = @itemBarcode", cn);
cmd.Parameters.Add(new SqlParameter("@itemBarcode", sBillItemBartxt.Text.Trim()));
cmd.CommandType = CommandType.Text;
// Executing the Query on the Database.
SqlDataReader resultsReader = cmd.ExecuteReader();
// Checking to see if the query has results
if (resultsReader.HasRows)
{
Dictionary<string, string> results = new Dictionary<string, string>();
// Results found looping through each result
while (resultsReader.Read())
{
results.Add(resultsReader["itmBar"].ToString(), resultsReader["itmName"].ToString());
}
// Checking to see if only one record was returned.
if (results.Count == 1)
{
// One item found displaying item name.
sBillItemNametxt.Text = results[sBillItemBartxt.Text.Trim()];
sBillItemNametxt.ReadOnly = true;
// not sure what this function call is doing
bindExDateGrid();
}
else
{
// Multiple records were found not sure if you need this.
MessageBox.Show("Multiple barcodes was found please try again");
}
}
else
{
// No Records was found in the database.
MessageBox.Show("No product found please try again");
}
}
}
catch (SqlException ex)
{
// There was an SQL error.
MessageBox.Show("An error occurred while Querying the database:" + Environment.NewLine + ex.Message);
}
catch (Exception ex)
{
// Final catch
MessageBox.Show("Unknown Error:" + Environment.NewLine + ex.Message);
}
}
// Resetting form elements.
sBillItemBartxt.Text = "";
sBillItemBartxt.Focus();
希望这有帮助