【问题标题】:How to edit a database from another form c#如何从另一个表单c#编辑数据库
【发布时间】:2015-09-08 05:17:57
【问题描述】:

我是 Visual C# 的新手。我正在尝试使用数据库创建一个程序来注册产品和客户。我只是跟着这两个演练:

Creating a Local Database File in Visual Studio

Connecting to Data in a Local Database File (Windows Forms)

然后我在我的解决方案上创建了 3 个表单:

Form1:在几秒钟后隐藏并打开 Form2 的初始屏幕。

Form2:有 4 个面板,[A] 为产品添加新寄存器和编辑寄存器(我在“详细信息”模式下拖放表格),[B] 使用 DataGridView,其中单元格配置为只读 = true。其他 2 个面板与客户相同。

Form3:双击 DataGridView 中的单元格时打开的对话框。此对话框显示的产品数据只有几个可编辑的字段。

我的问题:

如果我在 Form2 [A] 上编辑一个字段并保存它,我可以在 DataGridView [B] 和 Form3 上看到更改。

如果我在 Form3 上编辑一个字段并保存它,然后关闭对话框,Form2 上没有任何更改,无论是面板 [A] 还是面板 [B]。但是当我再次打开 Form3 时,编辑的数据就在那里。如果我在 [A] 上编辑我在 Form3 上编辑的相同字段并尝试保存,则会出现以下错误:

LojaEstiloDesign20150906.exe 中出现“System.Data.DBConcurrencyException”类型的未处理异常

附加信息:并发冲突:UpdateCommand 影响了预期的 1 条记录中的 0 条。”


这似乎是一个非常基本的问题,但我不知道如何解决它。我已经尝试了很多东西,但都没有奏效。 任何帮助将不胜感激。

表格2:

namespace LojaEstiloDesign20150906
{
public partial class frm_Menu : Form
{
    public frm_Menu()
    {
        InitializeComponent();
    }

    private void CadProdutosToolStripMenuItem_Click(object sender, EventArgs e)
    {
        panel_CadastroProdutos.Visible = true;
        panel_CadastroProdutos.Dock = DockStyle.Fill;

        panel_CadastroClientes.Visible = false;
        panel_ConsultaClientes.Visible = false;
        panel_ConsultaProdutos.Visible = false;
    }

    private void CadClientesToolStripMenuItem_Click(object sender, EventArgs e)
    {
        panel_CadastroClientes.Visible = true;
        panel_CadastroClientes.Dock = DockStyle.Fill;

        panel_CadastroProdutos.Visible = false;
        panel_ConsultaClientes.Visible = false;
        panel_ConsultaProdutos.Visible = false;
    }

    private void ConProdutosToolStripMenuItem1_Click(object sender, EventArgs e)
    {
        panel_ConsultaProdutos.Visible = true;
        panel_ConsultaProdutos.Dock = DockStyle.Fill;

        panel_CadastroClientes.Visible = false;
        panel_ConsultaClientes.Visible = false;
        panel_CadastroProdutos.Visible = false;
    }

    private void ConClientesToolStripMenuItem1_Click(object sender, EventArgs e)
    {
        panel_ConsultaClientes.Visible = true;
        panel_ConsultaClientes.Dock = DockStyle.Fill;

        panel_CadastroClientes.Visible = false;
        panel_ConsultaProdutos.Visible = false;
        panel_CadastroProdutos.Visible = false;
    }

    private void frm_Menu_FormClosing(object sender, FormClosingEventArgs e)
    {
        Application.Exit();
    }

    private void produtosBindingNavigatorSaveItem_Click(object sender, EventArgs e)
    {
        this.Validate();
        this.produtosBindingSource.EndEdit();
        this.tableAdapterManager.UpdateAll(this.lojaEstiloDataSet);

    }

    private void frm_Menu_Load(object sender, EventArgs e)
    {
        // TODO: This line of code loads data into the 'lojaEstiloDataSet.Clientes' table. You can move, or remove it, as needed.
        this.clientesTableAdapter.Fill(this.lojaEstiloDataSet.Clientes);
        // TODO: This line of code loads data into the 'lojaEstiloDataSet.Produtos' table. You can move, or remove it, as needed.
        this.produtosTableAdapter.Fill(this.lojaEstiloDataSet.Produtos);
    }

    private void produtosDataGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        frm_FichaProdutos frm3 = new frm_FichaProdutos();
        frm3.Show();
    }

    private void toolStripButton6_Click(object sender, EventArgs e)
    {
        this.Validate();
        this.clientesBindingSource.EndEdit();
        this.tableAdapterManager.UpdateAll(this.lojaEstiloDataSet);
    }
}
}

Form3:

namespace LojaEstiloDesign20150906
{
public partial class frm_FichaProdutos : Form
{
    public frm_FichaProdutos()
    {
        InitializeComponent();
    }


    private void frm_FichaProdutos_Load(object sender, EventArgs e)
    {
        // TODO: This line of code loads data into the 'lojaEstiloDataSet.Produtos' table. You can move, or remove it, as needed.
        this.produtosTableAdapter.Fill(this.lojaEstiloDataSet.Produtos);
        // TODO: This line of code loads data into the 'lojaEstiloDataSet.Produtos' table. You can move, or remove it, as needed.
        this.produtosTableAdapter.Fill(this.lojaEstiloDataSet.Produtos);

    }

    public void produtosBindingNavigatorSaveItem_Click_1(object sender, EventArgs e)
    {
        this.Validate();
        this.produtosBindingSource.EndEdit();
        this.tableAdapterManager.UpdateAll(this.lojaEstiloDataSet);

    }
}
}

【问题讨论】:

  • 在你的表单中 this.produtosTableAdapter.Fill(this.lojaEstiloDataSet.Produtos);行重复两次。而在 form2 中,您有 private void frm_Menu_Load(object sender, EventArgs e) { // TODO:这行代码将数据加载到“lojaEstiloDataSet.Clientes”表中。您可以根据需要移动或移除它。 this.clientesTableAdapter.Fill(this.lojaEstiloDataSet.Clientes); // TODO: 这行代码将数据加载到“lojaEstiloDataSet.Produtos”表中。您可以根据需要移动或移除它。 this.produtosTableAdapter.Fill(this.lojaEstiloDataSet.Produtos);}
  • @amitdayama 你应该把这个放到你的帖子里。请避免在 cmets 中给出答案。

标签: c# mysql database winforms visual-studio-2015


【解决方案1】:

ADO.NET 默认使用乐观并发。这意味着它存储两个版本的数据(原始和当前),然后,当您尝试保存对现有记录的修改时,它会将原始版本与数据库中的内容进行比较,以确保它们在保存之前匹配。这个想法是,它可以防止两个用户都检索相同的数据,并且都试图保存更改并让第二个保存覆盖第一个所做的更改。

在您的情况下,这不是两个不同的用户拥有两个不同的应用程序实例。它是同一个应用程序实例中的两种形式。您正在检索第一个表单中的数据,检索第二个表单中的数据,保存第二个表单中的更改,然后尝试保存第一个表单中的更改。第一种形式的数据的原始版本与数据库中的数据不匹配,因此会发生并发冲突。

对于如何继续,您有两种选择。在有效的并发冲突中,即两个不同的用户,您将捕获异常然后决定做什么,这可能是再次获取数据并让用户重新编辑或可能合并他们的更改。在你的情况下,这不是要走的路。您应该丢弃第一个表单中的数据,并在第二个表单关闭时再次获取它,否则一开始就不要两次获取相同的数据。

在第二个选项中,不是第二个表单获取自己的数据,而是第一个表单可以将它已经拥有的数据传递给它。因为只有一份数据副本,所以它将始终与数据库保持同步。

【讨论】:

  • 谢谢@jmcilhinney。如果我在打开 Form3 后关闭 Form2,然后在 Form3 关闭时再次打开 Form2,它会起作用。但是我更喜欢在 Form2 始终打开的情况下执行此操作,一旦使用向导完成所有数据库配置,如何关闭 Form2 的连接?
  • 当然,如果您关闭表单,它会起作用。我说了什么?如果您丢弃数据并再次获取它,那么问题就会消失。您不认为关闭表单并再次打开它会这样做吗?不过,您实际上并不需要关闭表单。照我说的做,即丢弃你拥有的数据并再次从数据库中获取它。
猜你喜欢
  • 2019-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-31
相关资源
最近更新 更多