【问题标题】:Unique bool check in DataGridView, updating the databaseDataGridView中唯一的布尔检查,更新数据库
【发布时间】:2013-06-05 12:07:13
【问题描述】:

我有一个带有位列的 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 中的两条记录。首先我希望 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,即选择查询提供图片表中属于该组成员的所有记录。

【问题讨论】:

  • 为什么打电话给table.AcceptChanges()?此表是否与更新命令中使用的表相同?
  • 请显示实际更新查询。当您说您正在使用 select query for the whole table 更新数据库时,您是否说错了?
  • 好吧,我必须传入一个查询才能实例化 SqlDataAdapter,我想...我将使用我使用的查询进行更新。
  • 是的,史蒂夫。如果我不调用 AcceptChanges,我永远不会从底层 DataTable 中获得 RowChanged 事件,因此我不知道启动执行更新的线程。
  • 此外,如果 IsDefault 列未绑定并且您保留一个单独的表,其中包含单行,其中包含主表中默认行的 id,则可能会更容易。然后,您可以简单地覆盖辅助表中的 id 值,而不必从主表的一行中删除默认标志并将其重新应用到另一行。

标签: c# sql-server winforms


【解决方案1】:

AcceptChanges 的调用将表中每一行的RowState 更改为未更改。
随后对 DataAdatper.Update(table) 的调用找不到任何要更新/插入或删除的内容。

您需要在用户输入时调用更新(例如单击保存按钮)

编辑 用@Robinson 的以下发现来完成这个答案

您可以为处理CurrentCellDirtyStateChanged 事件的表引发RowChanged 事件并在DataGridView 上手动提交编辑。否则,当行失去焦点时会引发 RowChanged 事件。

【讨论】:

  • 正如我对上一个答案所说(似乎已被删除),除非我调用AcceptChanges,否则我不知道表何时更新。 RowChanged 事件根本不会触发,我使用它来知道何时启动执行实际更新的线程。其次,当我只修改一行时(当我没有将其他行设置为 false 的代码时)它似乎有效。
  • 您可以尝试在没有 AcceptChanges 的情况下调用更新吗?只是为了排除这个 AcceptChanges 的事情。
  • 另外,我已经尝试了RowChanged here 上的示例。引发事件 RowChanged 以响应带有参数 Action = Commit 的 AcceptChanges,但是当您添加新行 (Action=Add) 和更改行字段 (Action=Change) 时,您也会收到 RowChanged 事件
  • 根据 Steve 在此处的评论,请参阅我对上述虚假并发违规错误的评论。发生的情况是,在单击后的第一次更新之后,您对 dataAdapter 说没有更多“脏”行,因此需要更新零行,因此当您调用更新命令时,受影响的行 = 0,因此正在引发(虚假)并发错误。
  • 好吧,我不懂DataGridView。当我通过单击打开/关闭复选框时,我没有收到 RowChanged 事件。除了切换它的复选框之外,它似乎什么都不做。
【解决方案2】:

这里有两个问题

首先,DataGridView 事件不会发送以正确缓存更改,您必须使用其他事件,例如 按钮单击,以强制 DataGridView 缓存更改.

另一个问题“并发冲突”是由在具有标识列(通常是主键)的表中插入新行引起的。我建议使用另一个按钮进行插入并在 DataGridView 中强制使用新的标识值。

当你更新时,我建议先删除,然后再进行更新:

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

// Next process updates.
da.Update(dt.Select(null, null, DataViewRowState.ModifiedCurrent));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    相关资源
    最近更新 更多