我必须使用以下代码更新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行的所有行都使用相同的最后一行
进行更新这是输入数据:
点击“保存”按钮后,它将是:
这是我的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
这是正确的结果:
答案 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并重复使用该参数,直到循环结束。