C# 如何处理参数化查询需要未提供的参数

C# 如何处理参数化查询需要未提供的参数,c#,exception-handling,C#,Exception Handling,我正在通过单击按钮插入数据。我正在尝试处理该字段的异常。我的代码是: try { con.Open(); SqlCommand cmd = new SqlCommand(); cmd.CommandText = "INSERT INTO omotnica (id,name,date,number)" + "VALUES(@id,@nazi

我正在通过单击按钮插入数据。我正在尝试处理该字段的异常。我的代码是:

try
        {
            con.Open();
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "INSERT INTO omotnica (id,name,date,number)" +
                                    "VALUES(@id,@naziv_predmeta,@date,@number)";

            cmd.Parameters.Add("@id", SqlDbType.Int).Value = idInt;
            cmd.Parameters.Add("@name", SqlDbType.NVarChar, 300).Value = this.textBoxName.Text;
            try
            {
                DateTime datt = DateTime.Parse(textBoxDatumUpisa.Text);
                textBoxDatumUpisa.Text = datt.ToString("d/M/yyyy");
                cmd.Parameters.Add("@date", SqlDbType.DateTime).Value = datt;
            }
            catch (FormatException)
            {
                MessageBox.Show("Date must be dd/MM/yyyy"); 
            }
            try
            {
                cmd.Parameters.Add("@number", SqlDbType.Int).Value = Convert.ToInt32(textBoxNumber.Text);

            }
            catch (SqlException e) when (e.Number == 8178)
            {
                MessageBox.Show("U must enter something");
            }
            catch (FormatException)
            {
                MessageBox.Show("It must be an integer");
            }

            con.Close();
             MessageBox.Show("Saved!");

        }
        catch (Exception ex)
        {
            MessageBox.Show(" error" + ex.Message + ex.Source );

        }try
        {
            con.Open();
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "INSERT INTO omotnica (id,name,date,number)" +
                                    "VALUES(@id,@naziv_predmeta,@date,@number)";

            cmd.Parameters.Add("@id", SqlDbType.Int).Value = idInt;
            cmd.Parameters.Add("@name", SqlDbType.NVarChar, 300).Value = this.textBoxName.Text;
            try
            {
                DateTime datt = DateTime.Parse(textBoxDatumUpisa.Text);
                textBoxDatumUpisa.Text = datt.ToString("d/M/yyyy");
                cmd.Parameters.Add("@date", SqlDbType.DateTime).Value = datt;
            }
            catch (FormatException)
            {
                MessageBox.Show("Date must be dd/MM/yyyy"); 
            }
            try
            {
                cmd.Parameters.Add("@number", SqlDbType.Int).Value = Convert.ToInt32(textBoxNumber.Text);

            }
            catch (SqlException e) when (e.Number == 8178)
            {
                MessageBox.Show("U must enter something");
            }
            catch (FormatException)
            {
                MessageBox.Show("It must be an integer");
            }

            con.Close();
             MessageBox.Show("Saved!");

        }
        catch (Exception ex)
        {
            MessageBox.Show(" error" + ex.Message + ex.Source );

        }
当我在textBoxNumber中输入某个字符串时,它会触发FormatException,也会触发异常。参数化查询需要未提供的参数。当我将textBox留空时,它会触发参数化查询需要未提供的参数。 如何更改?我没有用SQLException捕获覆盖该异常吗? 我需要它在文本框中为空或不是整数时触发消息框。

只需添加:
if(textbox.Text==string.Empty)返回在单击事件的开始处,这样就不会发生这种情况。
不要捕获这么多的异常并显示消息框,而是添加
if
条件,只处理应该发生的异常

如果您想接收
int
输入,请使用
numbericUpDown
只需添加:
if(textbox.Text==string.Empty)返回在单击事件的开始处,这样就不会发生这种情况。
不要捕获这么多的异常并显示消息框,而是添加
if
条件,只处理应该发生的异常


如果您想接收
int
输入,请使用
numbericUpDown

,您可以安全地尝试转换,而不会出现这样的异常

int num;
if (!Int32.TryParse(textBoxNumber.Text, out num)) {
    MessageBox.Show("It must be an integer");
    return;
}
Omotnica o = GetValues();
if (o == null) {
    MessageBox.Show("Please enter something for number, name, ...");
} else {
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "INSERT INTO omotnica (id,name,date,number) VALUES (@id,...";
    cmd.Parameters.Add("@id", SqlDbType.Int).Value = o.ID;
    cmd.Parameters.Add("@name", SqlDbType.NVarChar, 300).Value = o.Name;
    ...
}
以及可能为空的文本列

object textValue = String.IsNullOrWhiteSpace(textBoxName.Text)
    ? (object)textBoxName.Text
    : (object)DBNull.Value;
请注意,您必须传递
DBNull.Value
,而不仅仅是
null
作为参数,否则该参数将被视为丢失

如果要改为显示错误消息:

if(String.IsNullOrWhiteSpace(textBoxName.Text)) {
    MessageBox.Show("It must be an integer");
    return;
}

但是如果您试图转换文本框值,同时显示错误消息和构造SQL语句,代码就会变得非常混乱

而是为这些值创建一个类

class Omotnica 
{
    public int ID { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public int Number { get; set; }
}
在第一步中,将值放入这个类中。这也可以通过以下方式完成。这将为您完成所有转换

然后设置SQL命令会容易得多

如果仍然希望手动处理文本框值,可以为此创建一个方法

private Omotnica GetValues()
{
    var o = new Omotnica();
    if (!Int32.TryParse(textBoxNumber.Text, out o.Number)) {
        return null;
    }

    if(String.IsNullOrWhiteSpace(textBoxName.Text)) {
        return null;
    }
    o.Name = textBoxName.Text;

    ... and so on
}
然后可以像这样清理SQL部分

int num;
if (!Int32.TryParse(textBoxNumber.Text, out num)) {
    MessageBox.Show("It must be an integer");
    return;
}
Omotnica o = GetValues();
if (o == null) {
    MessageBox.Show("Please enter something for number, name, ...");
} else {
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "INSERT INTO omotnica (id,name,date,number) VALUES (@id,...";
    cmd.Parameters.Add("@id", SqlDbType.Int).Value = o.ID;
    cmd.Parameters.Add("@name", SqlDbType.NVarChar, 300).Value = o.Name;
    ...
}

看起来更整洁,不是吗?

您可以安全地尝试转换,而不会出现这样的异常

int num;
if (!Int32.TryParse(textBoxNumber.Text, out num)) {
    MessageBox.Show("It must be an integer");
    return;
}
Omotnica o = GetValues();
if (o == null) {
    MessageBox.Show("Please enter something for number, name, ...");
} else {
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "INSERT INTO omotnica (id,name,date,number) VALUES (@id,...";
    cmd.Parameters.Add("@id", SqlDbType.Int).Value = o.ID;
    cmd.Parameters.Add("@name", SqlDbType.NVarChar, 300).Value = o.Name;
    ...
}
以及可能为空的文本列

object textValue = String.IsNullOrWhiteSpace(textBoxName.Text)
    ? (object)textBoxName.Text
    : (object)DBNull.Value;
请注意,您必须传递
DBNull.Value
,而不仅仅是
null
作为参数,否则该参数将被视为丢失

如果要改为显示错误消息:

if(String.IsNullOrWhiteSpace(textBoxName.Text)) {
    MessageBox.Show("It must be an integer");
    return;
}

但是如果您试图转换文本框值,同时显示错误消息和构造SQL语句,代码就会变得非常混乱

而是为这些值创建一个类

class Omotnica 
{
    public int ID { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public int Number { get; set; }
}
在第一步中,将值放入这个类中。这也可以通过以下方式完成。这将为您完成所有转换

然后设置SQL命令会容易得多

如果仍然希望手动处理文本框值,可以为此创建一个方法

private Omotnica GetValues()
{
    var o = new Omotnica();
    if (!Int32.TryParse(textBoxNumber.Text, out o.Number)) {
        return null;
    }

    if(String.IsNullOrWhiteSpace(textBoxName.Text)) {
        return null;
    }
    o.Name = textBoxName.Text;

    ... and so on
}
然后可以像这样清理SQL部分

int num;
if (!Int32.TryParse(textBoxNumber.Text, out num)) {
    MessageBox.Show("It must be an integer");
    return;
}
Omotnica o = GetValues();
if (o == null) {
    MessageBox.Show("Please enter something for number, name, ...");
} else {
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "INSERT INTO omotnica (id,name,date,number) VALUES (@id,...";
    cmd.Parameters.Add("@id", SqlDbType.Int).Value = o.ID;
    cmd.Parameters.Add("@name", SqlDbType.NVarChar, 300).Value = o.Name;
    ...
}
看起来更整洁,不是吗?

Convert.ToInt32(String.Empty)将引发FormatException,因为它无法将空字符串解析为Int32值

将无效字符串转换为Int32将引发FormatException,但也会引发SQLException,因为转换失败,还会引发参数化查询,因为它需要Int32

您可以捕获System.Exception并打开可能的错误,而不是尝试捕获两个异常:

catch (Exception ex)            
{                
    if (ex is FormatException)
    {
        if (string.IsNullOrEmpty(this.textboxName.Text){ 
            MessageBox.Show("U must enter something");
        } else {
            MessageBox.Show("It must be an integer");
        }
        return; 
     } 
     else if (ex is SqlException) {
        MessageBox.Show(ex.Message);
        return;
     }
   throw;
}
Convert.ToInt32(String.Empty)将引发FormatException,因为它无法将空字符串解析为Int32值

将无效字符串转换为Int32将引发FormatException,但也会引发SQLException,因为转换失败,还会引发参数化查询,因为它需要Int32

您可以捕获System.Exception并打开可能的错误,而不是尝试捕获两个异常:

catch (Exception ex)            
{                
    if (ex is FormatException)
    {
        if (string.IsNullOrEmpty(this.textboxName.Text){ 
            MessageBox.Show("U must enter something");
        } else {
            MessageBox.Show("It must be an integer");
        }
        return; 
     } 
     else if (ex is SqlException) {
        MessageBox.Show(ex.Message);
        return;
     }
   throw;
}

在出现异常之前进行验证怎么样?这也是一个解决方案。我只是想说明为什么他的代码没有按预期工作,以及处理多个异常的另一种方法……但我也会先验证文本框,留下异常来处理更复杂的事情,比如SQLException。在出现异常之前进行验证怎么样?这也是一个解决方案。我只是想说明为什么他的代码没有按预期工作,以及处理多个异常的另一种方法……但我也会先验证textbox,留下异常来处理更复杂的事情,比如SQLExceptionOni不想传递dbnull.value。我想让它显示一个消息框,并让用户更正字段,然后插入它我不想传递一个dbnull.value。我想让它显示一个消息框,让它让用户更正字段,然后插入它