即使输入的数据正确,仍会显示异常消息

时间:2017-01-03 19:02:35

标签: c# winforms

我有一个具有自动完成模式的文本框,其值表示为项目条形码,我想检查一下如果这个条形码确实存在于数据库中,那么附上与该条形码相关的项目名称,当我输入无效的条形码,它给这个捕获消息和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();
    }
}

1 个答案:

答案 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

参数化SQL查询

同样@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();

希望这有帮助