只有Datagridview的最后一行更新了错误

时间:2017-10-03 07:27:16

标签: c# datagridview

我必须使用以下代码更新Dataridview:

private void tbrSave_Click(object sender, EventArgs e)
{
    try
    {
        SqlConnection sqlConn = new SqlConnection(strConStr);
        sqlConn.Open();

            var cmdUpdate = new SqlCommand("proc_TBL_PROC_PN_Update", sqlConn);
            cmdUpdate.CommandType = CommandType.StoredProcedure;
            foreach (DataGridViewRow item in grdProcess.Rows)
            {
                if (!item.IsNewRow)
                {
                    cmdUpdate.Parameters.Clear();
                    cmdUpdate.Parameters.AddWithValue("@_PROCESS_INST_NO", txtInstNo.Text);
                    cmdUpdate.Parameters.AddWithValue("@_PROCESS_CONTENTS", item.Cells[4].Value);
                    cmdUpdate.Parameters.AddWithValue("@_PROCESS_DATE", item.Cells[5].Value);
                    cmdUpdate.Parameters.AddWithValue("@_DELIVERY_DATE", item.Cells[6].Value);
                    cmdUpdate.Parameters.AddWithValue("@_OPT_MACHINE_NAME", item.Cells[7].Value);
                    cmdUpdate.ExecuteNonQuery();
                }
            }
        sqlConn.Close();
        sttlblMessage.Text = "Data has been updated successfully.";

    }
    catch
        (Exception ex)
    {

        MessageBox.Show(ex.ToString());
    }
}

但只有此DataGridview行的所有行都使用相同的最后一行

进行更新

这是输入数据:

enter image description here

点击“保存”按钮后,它将是:

enter image description here

这是我的SQL sp:

ALTER PROCEDURE [dbo].[proc_TBL_PROC_PN_Update]
    @_PROCESS_INST_NO nvarchar(50),
    @_PROCESS_CONTENTS  nvarchar(50),
    @_PROCESS_DATE nvarchar(50),
    @_DELIVERY_DATE nvarchar(50),
    @_OPT_MACHINE_NAME nvarchar(50)     
AS
    UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] SET _PROCESS_CONTENTS=@_PROCESS_CONTENTS,_PROCESS_DATE=@_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,_OPT_MACHINE_NAME=@_OPT_MACHINE_NAME
    WHERE _PROCESS_INST_NO=@_PROCESS_INST_NO

这是正确的结果:

enter image description here

2 个答案:

答案 0 :(得分:2)

您需要向表中添加主键(唯一索引)并使用它来识别您的记录。

您的查询:

UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] SET _PROCESS_CONTENTS=@_PROCESS_CONTENTS,_PROCESS_DATE=@_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,_OPT_MACHINE_NAME=@_OPT_MACHINE_NAME
WHERE _PROCESS_INST_NO=@_PROCESS_INST_NO

说“更新行_PROCESS_INST_NO = 79680这些字段”并且所有记录在该字段中具有相同的值,因此您的查询将影响所有记录,这就是为什么您在所有记录中都拥有foreach的最后一个值的原因

获得主键后,请更改foreach以使用它:

cmdUpdate.Parameters.AddWithValue("@Id", item.Cells[0].Value);
cmdUpdate.Parameters.AddWithValue("@_PROCESS_CONTENTS", item.Cells[4].Value);
cmdUpdate.Parameters.AddWithValue("@_PROCESS_DATE", item.Cells[5].Value);
cmdUpdate.Parameters.AddWithValue("@_DELIVERY_DATE", item.Cells[6].Value);
cmdUpdate.Parameters.AddWithValue("@_OPT_MACHINE_NAME", item.Cells[7].Value);

当然也会更改您的查询以使用主键:

UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] SET _PROCESS_CONTENTS=@_PROCESS_CONTENTS,_PROCESS_DATE=@_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,_OPT_MACHINE_NAME=@_OPT_MACHINE_NAME WHERE Id=@Id

答案 1 :(得分:2)

六行具有完全相同的 _PROCESS_INST_NO ,因此UPDATE会更改每个循环中的所有6行。您最终会得到包含上一个循环(最后一个网格行)值的所有行。

要更新单个记录,您需要在同一个表中提供LINE_NO参数,以区分具有相同_PROCESS_INST_NO的六行。

要改变的第一件事是SP接收LINE_NO参数并在where语句中使用它

ALTER PROCEDURE [dbo].[proc_TBL_PROC_PN_Update]
    @_PROCESS_INST_NO nvarchar(50),
    @_PROCESS_CONTENTS  nvarchar(50),
    @_PROCESS_DATE nvarchar(50),
    @_DELIVERY_DATE nvarchar(50),
    @_OPT_MACHINE_NAME nvarchar(50),
    @_LINE_NO nvarchar(50)     
AS
    UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] 
         SET _PROCESS_CONTENTS=@_PROCESS_CONTENTS,
             _PROCESS_DATE=@_PROCESS_DATE,  
             _DELIVERY_DATE = @_DELIVERY_DATE,
             _OPT_MACHINE_NAME=@_OPT_MACHINE_NAME
    WHERE _PROCESS_INST_NO=@_PROCESS_INST_NO 
      AND _LINE_NO = @_LINE_NO

然后更改代码以传递_LINE_NO字段的参数

    if (!item.IsNewRow)
    {
        cmdUpdate.Parameters.Clear();
        cmdUpdate.Parameters.AddWithValue("@_PROCESS_INST_NO", txtInstNo.Text);
        cmdUpdate.Parameters.AddWithValue("@_LINE_NO", item.Cells[3].Value);
        cmdUpdate.Parameters.AddWithValue("@_PROCESS_CONTENTS", item.Cells[4].Value);
        cmdUpdate.Parameters.AddWithValue("@_PROCESS_DATE", item.Cells[5].Value);
        cmdUpdate.Parameters.AddWithValue("@_DELIVERY_DATE", item.Cells[6].Value);
        cmdUpdate.Parameters.AddWithValue("@_OPT_MACHINE_NAME", item.Cells[7].Value);
        cmdUpdate.ExecuteNonQuery();
    }

另请注意,您的参数都是字符串类型。如果某些转换为数据库所需的实际数据类型并不像您期望的那样工作(例如日期是此模式的众所周知的问题来源),则可能会出现问题。始终使用正确数据类型的参数并执行not use AddWithValue

另一个小优化是在循环外部创建参数,而不为它们添加值。在循环内部,您不需要在每个循环中清除并重新添加每个参数,但您只需使用行单元格值更改Value并重复使用该参数,直到循环结束。