2

チェックボックスとして表示されるビット列を持つ DataGridView があります。列の名前は「IsDefault」です。これは、このセルがチェックされている場合、DataTable のこの列の他のすべてのセルをオフにする必要があることを意味します (この列の 1 つのセルのみをデフォルトにすることができます)。

DataGridView の CellContentClick イベントの変更を処理することで、この動作を機能させることができました。

private void ViewIconsDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex == -1 || e.ColumnIndex == -1)
        return;

    DataTable table = ViewIconsDataGrid.DataSource as DataTable;
    DataGridViewCell cell = ViewIconsDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex];
    Guid rowID = (Guid)ViewIconsDataGrid.Rows[e.RowIndex].Cells["ID"].Value;

    if (cell.GetType() == typeof(DataGridViewCheckBoxCell))
    {
        DataGridViewCheckBoxCell checkBoxCell = cell as DataGridViewCheckBoxCell;

        bool value = (bool)checkBoxCell.EditedFormattedValue, previous = (bool)checkBoxCell.Value;

        if (value != previous)
        {
            if (value == true)
            {
                Guid currentDefault;

                if(MyIcons.Defaults.TryGetValue(MyGroupID, out currentDefault))
                {
                    DataRow [] rows = table.Select("ID = '" + currentDefault.ToString() + "'");

                    if(rows.Length == 1)
                    {
                        rows[0]["IsDefault"] = false;
                    }
                }
            }

            ViewIconsDataGrid.EndEdit(); table.AcceptChanges();
        }
    }
}

ここで、同じ DataTable 内の 2 つのレコードを変更しようとしていることは明らかです。最初に、DataGridView が変更されることを望んでいます (ユーザーがチェックボックスの状態を変更したとき)。次に、DataTable で別の変更を行って、既にチェックされている行のチェックを外し、DataGridView まで伝播することを望んでいます。もちろん、両方の変更をデータベースにコミットする必要があります。

これは私のデータベースの「更新」コードです。これは一種の一般的なものです。つまり、テーブル全体の選択クエリと更新対象のデータ テーブルを渡します。

using (SqlConnection connection = new SqlConnection(ConfigurationManager.AppSettings["Connection"]))
{
    connection.Open();

    using (SqlDataAdapter adapter = new SqlDataAdapter(MyQuery, connection))
    {
        adapter.InsertCommand = new SqlCommandBuilder(adapter).GetInsertCommand();
        adapter.DeleteCommand = new SqlCommandBuilder(adapter).GetDeleteCommand();
        adapter.UpdateCommand = new SqlCommandBuilder(adapter).GetUpdateCommand();

        adapter.Update(MyTable);
    }
}

したがって、問題は、これらの変更を行った後にテーブルを更新しようとすると、例外が発生することです:「同時実行違反: UpdateCommand は、予想される 1 レコードの 0 に影響を与えました。」既存のデフォルトがない場合は、単一のレコードのみが更新され、すべて問題ありません。

誰かが私の間違いを見つけたり、これを行うためのより簡単な方法を見つけたりできますか?

編集 1: 上記のフラグメントでは、MyQueryは次のようになります。

@"SELECT * From Picture WHERE ID_Group = '{0}' AND Deleted = 0 ORDER BY Created DESC

{0} は、更新中の画像グループの GUID です。つまり、選択クエリは、そのグループのメンバーである画像テーブル内のすべてのレコードを提供します。

4

2 に答える 2

0

ここには2 つの問題があります。

まず、DataGridView イベントは変更を正しくキャッシュするために送信されません。ボタン クリックなどの他のイベントを使用して、DataGridView に変更を強制的にキャッシュさせる必要があります。

もう 1 つの問題「同時実行違反」は、Identity 列 (通常は主キー) を持つテーブルに新しい行を挿入することによって発生します。挿入には別のボタンを使用し、DataGridView で新しい ID 値を強制することをお勧めします。

更新するときは、最初に削除を行い、次に更新を行うことをお勧めします。

// First process deletes.
da.Update(dt.Select(null, null, DataViewRowState.Deleted));

// Next process updates.
da.Update(dt.Select(null, null, DataViewRowState.ModifiedCurrent));
于 2016-12-15T12:08:39.343 に答える