我的id不为空,为什么我会收到运行时错误

本文关键字:运行时错误 为什么 id 我的 | 更新日期: 2023-09-27 18:28:42

我收到这个运行时错误,我的id不为空。我在代码中检查了它,你会看到,我正在使用telerik GridView

这是运行时错误

参数化查询"(@_fName nvarchar(4)、@_lName nvarcher(2)、@_phone nvarchar)(6)、@_a"需要参数"@_id",但未提供该参数。

我正试图从另一个表单中获取id,这就是为什么我这样写

这是我的第一层中的代码

private void btnEdt_Click(object sender, EventArgs e)
{
        Ref_View_Model = new View_model._View_Model();
        Ref_C = new Customers();
        foreach (var RowInfo in Ref_C.radGridView1.SelectedRows)
        {
            FireCell = RowInfo.Cells[0].Value.ToString();
            if (FireCell==null)
            {
                MessageBox.Show("null");
            }
        }
        //Ref_C.radGridView1.CurrentRow.Delete();
        Ref_C.customersTableAdapter.Update(Ref_C.sales_and_Inventory_SystemDataSet);
        Ref_C.customersTableAdapter.Fill(Ref_C.sales_and_Inventory_SystemDataSet.Customers);
        Ref_View_Model.GetEditCustomers(FireCell, txtFName.Text, txtLName.Text, txtPhn.Text, txtDdrss.Text);
} 

这是我在最后一层中的代码

public void EditCustomres( string _id,string _fName, string _lName,string _phone, string _address)
{
        Connection_String = @"Data Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=TrueData Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=True;";
        Query = "update Customers " +
                                "set FName=@_fName  ,LName=@_lName  ,Phone=@_phone ,[Address]=@_address" +" "+
                                  "where Id like @_id";
        using (Con=new SqlConnection(Connection_String))
        using (Cmd=new SqlCommand(Query,Con))
        {
            Cmd.Parameters.Add("@_fName", SqlDbType.NVarChar);
            Cmd.Parameters.Add("@_lName", SqlDbType.NVarChar);
            Cmd.Parameters.Add("@_phone", SqlDbType.NVarChar);
            Cmd.Parameters.Add("@_address", SqlDbType.NVarChar);
            Cmd.Parameters.Add("@_id", SqlDbType.Int);
            Con = Cmd.Connection;
            Con.Open();
            Cmd.Parameters["@_fName"].Value = _fName;
            Cmd.Parameters["@_lName"].Value = _lName;
            Cmd.Parameters["@_phone"].Value = _phone;
            Cmd.Parameters["@_address"].Value = _address;
            Cmd.Parameters["@_id"].Value = _id;
            Cmd.ExecuteNonQuery();
            Cmd.Dispose();
            }
} 

我的id不为空,为什么我会收到运行时错误

在这种情况下,你真的不想使用LIKE,除非你有非常特殊的需求,让它更新看起来像你传递的ID,但不完全是…

您将@_id作为SqlDbType.Int传递,但该变量的类型实际上是string,这将导致在后台进行转换。如果您传入一个空字符串,则该值将转换为null,这将导致您在文章中提到的错误。检查导致调用EditCustomres的代码,以确保它实际传递了正确的值。添加参数检查,就像我添加的那样,将帮助您在调用堆栈中更早地跟踪这类问题。

第一步是去掉LIKE语句,因此请更新查询以使用:

where id = @_id

然后更新您的代码,因为您希望_id变量为int,所以不能只为其分配一个字符串,这可能就是它被重置为null的原因。更新方法以接受int参数而不是string id,或者在添加参数之前解析方法中的int

int idValue = -1;
if (!int.TryParse(_id, NumberStyles.Integer, CultureInfo.InvariantCulture, out idValue))
{
    throw new ArgumentException("id", "Id must be a string which contains an integer value, the value of 'id' was: '" + _id + "'"); 
}
Cmd.Parameters.Add("@_id", SqlDbType.Int).Value = idValue;

您可能需要在文件中添加一个using语句:

using System.Globalization;

这里定义了NumberStylesCultureInfo。通常,Visual Studio会建议您在哪里可以找到这些项目crtl+将弹出一个屏幕,该屏幕将自动添加此语句。


最终结果是:

using System.Globalization;
....
....
public void EditCustomers( string _id,string _fName, string _lName,string _phone, string _address)
{
    int idValue = -1;
    if (!int.TryParse(_id, NumberStyles.Integer, CultureInfo.InvariantCulture, out idValue))
    {
       string message = "Id must be a string which contains an integer value, the value of 'id' was: '" + _id + "'";
       throw new ArgumentException("_id", message); 
    }
    Connection_String = @"Data Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=TrueData Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=True;";
    Query = @"update Customers 
                  set FName=@_fName, LName=@_lName, Phone=@_phone,[Address]=@_address
                  where Id = @_id";
    using (Con=new SqlConnection(Connection_String))
    using (Cmd=new SqlCommand(Query, con))
    {
        Cmd.Parameters.AddWithValue("@_fName", _fName);
        Cmd.Parameters.AddWithValue("@_lName", _lName);
        Cmd.Parameters.AddWithValue("@_phone", _phone);
        Cmd.Parameters.AddWithValue("@_address", _address);
        Cmd.Parameters.AddWithValue("@_id", idValue);
        Con.Open();
        Cmd.ExecuteNonQuery();
    }
}   

我也简化了一些代码。为SQL语句使用逐字逐句的字符串,删除对Dispose的调用(using(cmd)的使用已经涵盖了这一点),并删除Con=Cmd.Connection,因为它实际上不可能有任何其他值。

使用.AddWithValue方法也比单独创建和设置值更容易。


对于需要在SQL Server端连接字符串以形成SQL查询的解决方案,要格外小心,这可能会导致值注入不需要的SQL语句,这些语句可能会将您的数据暴露给外部世界或允许外部人员销毁您的数据。

还要小心使用LIKE语句来匹配更新值。除非对调用该语句的代码路径进行非常强的参数验证,否则向函数传递id="?"id="%%"或简单的id=string.Empty可能会更新所有记录,从而覆盖所有记录,使其具有相同的值。%1%将匹配1、10、21、31、11、100003……这极不可能是所需的行为。

在删除和更新语句中使用=而不是like几乎总是所需的解决方案。如果=出现错误,则可能是混合了数据类型(例如,string中应为int)。

idLIKE子句不正确。应该是这样的:

Id LIKE '%' + @_id + '%'

或者:

Cmd.Parameters.AddWithValue("@_id","%" + _id+ "%");

或者:

Cmd.Parameters.Add("@_id", SqlDbType.Int).Value = "%" + _id + "%";

尽管最好使用简单的=而不是Like:

where Id = @_id