【问题标题】:Delete selected datatable row from database从数据库中删除选定的数据表行
【发布时间】:2014-11-05 10:07:10
【问题描述】:

我在 C# 的 DataGridView 中有一个数据表。我用从 MySql 数据库获得的值填充了这个表。现在,一旦我在 WinForm 端的数据表中添加任何新值,它就可以成功检索数据库表并添加到它。这是用于此目的的代码:

dbDataset.RowChanged += new DataRowChangeEventHandler(Row_Changed); // dbDataset is my datatable name

    private static void Row_Changed(object sender, DataRowChangeEventArgs e)
    {
            // here sda is my MySqlDataAdapter
            try
            {
                MySqlCommandBuilder cmdb = new MySqlCommandBuilder(sda);
                dbDataset.GetChanges();
                dbDataset.GetChanges(DataRowState.Added);
                dbDataset.GetChanges(DataRowState.Deleted);
                dbDataset.GetChanges(DataRowState.Detached);
                dbDataset.GetChanges(DataRowState.Modified);
                dbDataset.GetChanges(DataRowState.Unchanged);                    
                sda.Update(dbDataset);                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
    }

但是现在我发现当我想从表中删除任何一行时,例如我选择一行并按“删除”键,它会在屏幕上显示它已被删除,但是一旦我重新加载我的 WinForm,它仍然在那里。显然它没有从数据库中删除该选定的行。为此,经过一番搜索,我添加了以下部分:

dbDataset.RowDeleted += new DataRowChangeEventHandler(Row_Deleted);

    private static void Row_Deleted(object sender, DataRowChangeEventArgs e)
    {
        dbDataset.AcceptChanges();
    }

通过调试发现,当我按下“delete”键时,进入Row_Delete函数,然后进入Row_Changed函数,但抛出异常,说:

Additional information: Concurrency violation: the DeleteCommand affected 0 of the expected 1 records.

我搜索得到当前选择的行索引,这样我就可以使用 DataRow.delete 方法,例如:

CurrencyManager xCM = = (CurrencyManager)this.BindingContext[this.dataGridView1.DataSource, this.dataGridView1.DataMember];

Row_Deleted 函数中我添加了:

DataRowView xDRV = (DataRowView)xCM.Current;
DataRow xDR = ((DataRowView)xCM.Current).Row;
xDR.Delete();

但它给出了空异常,说dataGridView1的数据源不能为空。

有没有关于如何从数据库中删除所选行的想法?提前致谢。

【问题讨论】:

  • AcceptChanges 很棘手。它不会更新数据库上的任何内容。它只接受内存数据表上的更改。如果您调用它,则不会将任何内容写入数据库,因为每行的状态都将重置为未更改,并且已删除的行将从数据表中删除
  • 那么我应该怎么做才能从数据库中删除呢?
  • Row_Changed 事件中的代码应该可以工作(删除不需要的 GetChanges 调用)但是,我会在 button_click 事件(保存按钮)中编写该代码,而不是为每个更改的行执行它.如果我没记错的话,Update 调用会导致对 RowChanged 的​​递归调用。
  • 确实很棘手 :) 我按照你说的做了,删除了 Row_Changed 函数中的所有 GetChanges 调用,然后只保留了 Row_Deleted 函数中的 dbDataset.AcceptChanges() 行。现在它按预期工作。谢谢。
  • 我认为它起作用只是因为您在删除后进行了更改。使用 Update 调用对 RowChanged 的​​调用是使用更改更新数据库的调用。如果您只是删除一行而不进行任何其他更改,我认为您的行没有从数据库中删除。

标签: c# mysql sql winforms datatable


【解决方案1】:

我将使用两种不同的方法进行更新。一个用于插入/更新,一个用于删除。
当您删除行时,框架将调用 RowDeleted 事件处理程序,而不是 RowChanged。

private static void Row_Changed(object sender, DataRowChangeEventArgs e)
{
    try
    {
        MySqlCommandBuilder cmdb = new MySqlCommandBuilder(sda);
        sda.Update(dbDataset);                
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private void Row_Deleted(object sender, DataRowChangeEventArgs e)
{
    try
    {
        SqlCommandBuilder cmdb = new SqlCommandBuilder(da);
        da.Update(dt);                
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

您应该删除AcceptChanges 调用。根据 MSDN

当您在 DataSet 上调用 AcceptChanges 时,任何 DataRow 对象仍然 在编辑模式下成功结束他们的编辑。的 RowState 属性 每个 DataRow 也会发生变化;添加和修改的行变为未更改, 并删除已删除的行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多