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 [email protected]_PROCESS_CONTENTS,[email protected]_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,[email protected]_OPT_MACHINE_NAME
    WHERE [email protected]_PROCESS_INST_NO

そして、これが正しい結果です。

enter image description here

0
はい、購買発注のプロセスと同じ番号です
追加された 著者 user3035133,
私の最新の写真を見てください
追加された 著者 user3035133,
私の最新の写真を見てください
追加された 著者 user3035133,
txtInstNo.Textは常に同じIDを持っているのでしょうか。
追加された 著者 Isma,
それで、あなたはいつも同じ記録を更新していますか?したがって、常に最後の行(最後に実行したクエリ)の値に更新されます。
追加された 著者 Isma,
それで、あなたはいつも同じ記録を更新していますか?したがって、常に最後の行(最後に実行したクエリ)の値に更新されます。
追加された 著者 Isma,

4 答え

6行はすべて同じ _PROCESS_INST_NO であるため、UPDATEは各ループで6行すべてを変更します。最後のループの値を含むすべての行(最後のグリッド行)になります。

単一のレコードを更新するには、同じ_PROCESS_INST_NOを持つ6つの行と区別するために、同じテーブルにあるLINE_NOパラメータが必要です。

変更するべき最初の事柄はLINE_NOパラメータを受け取り、where文でそれを使用する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),
    @_LINE_NO nvarchar(50)     
AS
    UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] 
         SET [email protected]_PROCESS_CONTENTS,
             [email protected]_PROCESS_DATE,  
             _DELIVERY_DATE = @_DELIVERY_DATE,
             [email protected]_OPT_MACHINE_NAME
    WHERE [email protected]_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();
    }

Note also that your parameters are all of type string. This could be a problem if some conversion to the real data type required by your database doesn't work as you expect (dates for example are a well known source of problem with this pattern). Use always parameters of the correct datatype and do not use AddWithValue

もう1つのマイナーな最適化は、値を追加せずにパラメータの作成をループの外側に移動することです。ループ内では、各ループですべてのパラメータをクリアして追加し直す必要はありませんが、Valueを行のセル値で変更し、ループの最後までパラメータを再利用することができます。

2
追加された
これは私のために働きます。ありがとうございます。
追加された 著者 user3035133,

6行はすべて同じ _PROCESS_INST_NO であるため、UPDATEは各ループで6行すべてを変更します。最後のループの値を含むすべての行(最後のグリッド行)になります。

単一のレコードを更新するには、同じ_PROCESS_INST_NOを持つ6つの行と区別するために、同じテーブルにあるLINE_NOパラメータが必要です。

変更するべき最初の事柄はLINE_NOパラメータを受け取り、where文でそれを使用する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),
    @_LINE_NO nvarchar(50)     
AS
    UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] 
         SET [email protected]_PROCESS_CONTENTS,
             [email protected]_PROCESS_DATE,  
             _DELIVERY_DATE = @_DELIVERY_DATE,
             [email protected]_OPT_MACHINE_NAME
    WHERE [email protected]_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();
    }

Note also that your parameters are all of type string. This could be a problem if some conversion to the real data type required by your database doesn't work as you expect (dates for example are a well known source of problem with this pattern). Use always parameters of the correct datatype and do not use AddWithValue

もう1つのマイナーな最適化は、値を追加せずにパラメータの作成をループの外側に移動することです。ループ内では、各ループですべてのパラメータをクリアして追加し直す必要はありませんが、Valueを行のセル値で変更し、ループの最後までパラメータを再利用することができます。

2
追加された
これは私のために働きます。ありがとうございます。
追加された 著者 user3035133,

テーブルに主キー(一意のインデックス)を追加し、それを使ってレコードを識別する必要があります。

あなたの質問:

UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] SET [email protected]_PROCESS_CONTENTS,[email protected]_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,[email protected]_OPT_MACHINE_NAME
WHERE [email protected]_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 [email protected]_PROCESS_CONTENTS,[email protected]_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,[email protected]_OPT_MACHINE_NAME WHERE [email protected]
2
追加された
問題はこのTableが他の人々によって設計されていてそれがたくさんのデータを持っていたことです。彼らはこのアプリケーションをVB6で書きましたが、グリッドを更新することができます。今、私は古いテーブル構造を使わなければなりませんが、c#を使います。どうですか?なぜ彼らはこの複製されたINDEXNOでこのデータグリッドビューを更新することができますか?
追加された 著者 user3035133,
イスマありがとうございます!今うまくいく!
追加された 著者 user3035133,
テーブルを変更してPKを追加できない場合は、@ Steveが提案した解決策を使用してください。単に_PROCESS_INST_NOと_LINE_NOの組み合わせが一意であることを確認してください。
追加された 著者 Isma,

テーブルに主キー(一意のインデックス)を追加し、それを使ってレコードを識別する必要があります。

あなたの質問:

UPDATE [ENVNDIVDB].[dbo].[TBL_PROC_PN] SET [email protected]_PROCESS_CONTENTS,[email protected]_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,[email protected]_OPT_MACHINE_NAME
WHERE [email protected]_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 [email protected]_PROCESS_CONTENTS,[email protected]_PROCESS_DATE,  _DELIVERY_DATE = @_DELIVERY_DATE,[email protected]_OPT_MACHINE_NAME WHERE [email protected]
2
追加された
問題はこのTableが他の人々によって設計されていてそれがたくさんのデータを持っていたことです。彼らはこのアプリケーションをVB6で書きましたが、グリッドを更新することができます。今、私は古いテーブル構造を使わなければなりませんが、c#を使います。どうですか?なぜ彼らはこの複製されたINDEXNOでこのデータグリッドビューを更新することができますか?
追加された 著者 user3035133,
イスマありがとうございます!今うまくいく!
追加された 著者 user3035133,
テーブルを変更してPKを追加できない場合は、@ Steveが提案した解決策を使用してください。単に_PROCESS_INST_NOと_LINE_NOの組み合わせが一意であることを確認してください。
追加された 著者 Isma,