我的id不为null,为什么我收到运行时错误?

时间:2016-01-01 08:11:22

标签: c# sql winforms ado.net runtime-error

我收到此运行时错误且我的id不为空我在我的代码中检查了它,您将看到我正在使用 telerik GridView

这是运行时错误

  

参数化查询'(@_ fName nvarchar(4),@ _ lName nvarchar(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();
            }
} 

2 个答案:

答案 0 :(得分:2)

在这种情况下,你真的不想使用LIKE,除非你有非常具体的需要来更新看起来像你传入的ID的东西,但是它不是......

您作为@_id传递SqlDbType.Int,但该变量实际上是string类型,这将导致转换发生在引擎盖下。如果您传入一个空字符串,该值将转换为null,这将导致您在帖子中提到的错误。检查导致调用EditCustomres的代码,以确保它实际传递正确的值。添加参数检查(如我添加的参数检查)将帮助您更早地在callstack中跟踪这些类型的问题。

第一步是摆脱您的LIKE声明,因此请更新要使用的查询:

where id = @_id

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

int

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

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 System.Globalization; NumberStyles的地方。通常,Visual Studio会建议您可以在哪里找到这些项 crtl + 会弹出一个屏幕,自动添加此语句。

最终结果将是:

CultureInfo

我也简化了代码。对您的SQL语句使用逐字字符串,删除对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(); } } 的调用(已使用Dispose覆盖并删除using(cmd),因为它实际上不能包含任何其他值。

使用Con=Cmd.Connection方法也比单独创建和设置值更容易。

要非常小心需要连接字符串以在SQL Server端形成SQL查询的解决方案,这可能会导致值注入不需要的SQL语句,从而将数据暴露给外界或允许外人破坏你的数据。

还要注意.AddWithValue语句以匹配更新值。除非您对调用此语句的代码路径进行非常强大的参数验证,否则将LIKEid="?"或简称id="%%"传递给您的函数可能会更新所有记录,从而覆盖所有记录他们有相同的价值观。 %1%将匹配1,10,21,31,11,100003 ......这种行为极不可能。

在删除和更新语句中使用id=string.Empty而非=几乎总是所需的解决方案。如果您使用like收到错误,则可能会混合数据类型(=,例如,string

答案 1 :(得分:0)

LIKE的{​​{1}}条款不正确。它应该是这样的:

id

或者:

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

或者:

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

虽然最好使用简单的Cmd.Parameters.Add("@_id", SqlDbType.Int).Value = "%" + _id + "%"; 代替=

Like