【发布时间】: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