繁体   English   中英

C# Access数据库插入后不更新数据

[英]C# Access database doesn't update data after inserting

我正在做一个学校项目,我遇到了一个问题。 当我从数据库中插入/更新/删除数据时,在我重新启动应用程序之前不会显示数据。 我必须关闭应用程序并再次打开它才能显示更改。

当我更改OleDbConnection字符串时(当我更改源时),数据会更新,但它只会在我关闭应用程序之前显示,当我关闭应用程序时,我会丢失所有新数据。 数据库中的数据显示在dataGridView中。 当我为dataGridView选择数据源时,代码行会使用该代码自动写入表单加载事件中,当源更改为不保存数据的文件时,我可以更新数据。

我想知道添加新数据后是否还有其他方法可以自动刷新(或使用按钮) dataGridView 我正在使用VS C# 2008 速成版,因为这是我们在学校使用的那个。

下面是插入按钮的代码:

 private void buttonInsert_Click(object sender, EventArgs e)
    {

        konekcija.Open();
        OleDbCommand komanda = konekcija.CreateCommand();
        komanda.CommandType = CommandType.Text;
        komanda.CommandText = ("Insert into Sobe(Broj_sobe,Tip_sobe,Telefon,Stanje)values('"
            + textBoxBrSobe.Text + "','" + textBox2.Text +"','" + textBoxTelefon.Text + "','" + textBox1.Text + "')");
        komanda.ExecuteNonQuery();
        
        konekcija.Close();
        MessageBox.Show("Uspjeli ste");
//this is written automatically in form load event
        this.sobeTableAdapter1.Update(this.hotelDataSet1.Sobe);
    }

这是连接字符串,这是我在学校被教导的方式。

OleDbConnection konekcija = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:/Users/Pupo/Desktop/Hotel/Hotel/Hotel/Hotel.mdb;Persist Security Info=False");

当我将连接字符串更改为 go 到 bin/debug 文件夹时,它会自动更新但不保存数据。

OleDbConnection konekcija = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Hotel.mdb;Persist Security Info=False");

好的,您在更改连接字符串时遇到问题和不同行为的原因是以下之一:

  • 磁盘上有两个数据库,你找错了一个
  • 您以错误的方式进行数据访问

你正在打这两个。 首先,我将解释第一个。

当您将 access 数据库添加到您的项目中时(无论如何,有几种方法)这个对话框(或类似的 - 这是 vs 2019)可能会出现

X

它又长又无聊,并且告诉人们很多他们可能不理解的东西,所以他们只是点击“是”然后忘记它。 后来他们在尝试保存数据时会很困惑

这个框基本上是在说“我将把数据库复制到你的项目文件夹中,但请记住,每次按下播放时,它都会再次复制到 BIN 文件夹,并且你正在运行的程序将修改bin 文件夹中的数据库,而不是项目文件夹中的 db,而不是桌面(或任何地方)中的 db”

后来开发人员运行程序,保存了一些数据,在 Access 中查找,没有找到。 或者他们再次运行程序并想知道“我刚刚保存的数据到哪里去了”。

“每次运行程序时,项目文件夹中的 db 都会复制到 bin 文件夹中”

这意味着每次在 Visual Studio 中构建项目时,程序保存其数据的数据库都会被擦除和替换。 它不会影响实时应用程序(实时应用程序不会在每次运行时自行构建),只会影响您在 VS 中运行的应用程序

如果您查看 BIN 文件夹中的数据库以外的任何数据库,您将找不到数据,因为您正在查找错误的数据库

我建议您在解决方案资源管理器中找到您的数据库,右键单击它,选择属性并将“复制到输出”更改为“如果较新则复制”。 这样VS只会在您对项目文件夹中的数据库进行更改(即添加一个新表)时替换bin文件夹中的数据库 - 这更像是您想要做的,通常


现在我评论说您的数据访问不正确:

private void buttonInsert_Click(object sender, EventArgs e)
{

    konekcija.Open();
    OleDbCommand komanda = konekcija.CreateCommand();
    komanda.CommandType = CommandType.Text;
    komanda.CommandText = ("Insert into Sobe(Broj_sobe,Tip_sobe,Telefon,Stanje)values('"
        + textBoxBrSobe.Text + "','" + textBox2.Text +"','" + textBoxTelefon.Text + "','" + textBox1.Text + "')");
    komanda.ExecuteNonQuery();
    
    konekcija.Close();
    MessageBox.Show("Uspjeli ste");
    //this is written automatically in form load event
    this.sobeTableAdapter1.Update(this.hotelDataSet1.Sobe);
}

完全没有必要在您的应用程序中创建 OleDbCommand。 VS 在数据集 (HotelDataSet) 中为您编写所有代码。 TableAdapter 内部包含一个 OleDbCommand; 事实上有几个。 TableAdapter 是一种将数据从您的数据库下载到您的数据集中的设备,并且还负责在发生更改(新记录、更改的记录和删除的记录)时将其保存回数据库。

所有这些魔法都发生在tableadapter.Update(..) - 更新不只是运行更新。 它也运行插入和删除- 当您将数据下载到数据集中时,它最终存储在数据行中,在数据表中。 这与数据库非常相似。 DataRows 跟踪您的用户所做的事情 - 如果创建了新行并将其添加到数据表中,则它的 RowState 为已添加。 如果您更改现有行中的数据,则它的 state 为已修改。 如果您从数据表中删除该行,它将被标记为已删除。 当您调用tableadapter.Update(theDatatable)不同的 SQL INSERT/UPDATE/DELETE 将分别保存您对添加/修改/删除行所做的任何事情。 保存后,一行更改为 Unchanged state。 如果再次编辑它,它会再次变为Modified,所以调用Update时会再次保存

因此,如果您想在数据库中插入一行,您应该将其添加到数据表中,然后更新以保存它。 如果数据表正在由例如 DataGridView 查看,则网格将自动查看更改并在添加时显示它

大概是这样的:

//put this in a button click
hotelDataSet1.Sobe.AddSobeRow(textBoxBrSobe.Text, textBox2.Text, textBoxTelefon.Text, textBox1.Text);

现在该行将出现在 datagridview 中。 它不在数据库中,但仅在本地数据表中,这就像仅在客户端中的缓存/临时数据存储。 您必须保存它以使其 go 进入数据库。 这将保存数据:

this.sobeTableAdapter1.Update(this.hotelDataSet1.Sobe);

您声称是在表单加载中写的; 不是。 表单加载中的内容是调用Fill ,而不是Update 填充用于加载。 更新是为了保存。

当您将绑定网格添加到 forms 时,windows forms 使用数据集的默认行为是在表单加载时调用 Fill,以从数据库中下载所有数据,以便您查看。 它不会在表单加载中调用更新,因为表单是新的; 没有什么可更新的。 任何时候你想从你调用 Fill 的数据库中下载数据。

这就是为什么当您将连接字符串更改为指向不在 BIN 文件夹中的其他数据库时遇到第二个问题,然后您使用 OleDbCommand 将数据插入数据库 - 它仅在您重新加载程序时出现,因为您的表单加载调用填充,这是您的新数据从数据库获取到程序的方式。 因为您使用 OleDbCommand 进行直接插入,所以您完全超出了程序中内置的所有数据处理,并直接插入到数据库中。 您的程序永远不知道数据已写入; 您从未将数据存储在程序中连接到 UI 的任何内容中

当然,如果您只在加载表单时加载一次数据,那么您将不得不重新启动程序来加载数据。 这个想法是您也可以在其他时间调用 Fill; 不只是在表单加载。 我稍后会谈到这个

不要使用 OleDbCommands直接在您使用 tableadapter 的过程中插入数据; 这将导致混乱的世界,并且是一个糟糕的解决方案。 按预期使用表格适配器; 使用 tableadapter 将新数据加载到数据表(在数据集内),然后使用 tableadapter 保存表。 如果 tableadapter 没有加载/保存您想要的方式,您可以更改它:


现在,您实际上可能希望摆脱表单加载中将整个 db 表加载到本地数据集的这一行,因为我们很少下载所有数据。 将所有百万股票价格加载到应用程序中是一个坏主意; 只需加载您想要的

举个例子,打开项目中的 HotelDataSet 文件,找到一些 tableadapter,比如 SobeTableAdapter,右键单击它,选择 Add>>Query。 选择“选择返回行”,输入一个查询,如SELECT * FROM Sobe WHERE Broj_Sobe LIKE? ,称之为 FillByBrojSobe,完成向导。

现在在您的代码中,您可以搜索:

sobeTableAdapter1.FillByBrojSobe(this.HotelDataSet.Sobe, "ABC"); // fill only records with a Broj_Sobe = "ABC"

或者

sobeTableAdapter1.FillByBrojSobe(this.HotelDataSet.Sobe, "DEF%"); // fill only records with a Broj_Sobe starting with "DEF"

记录被填充到HotelDataSet.Sobe中。 任何与此绑定的 datagridview(即这样的一行代码会将网格绑定到数据: datagridViewSobe.DataSource = HotelDataSet.Sobe - 这通常在 forms 设计器中完成,因此您在您的项目*) 将自动刷新以显示您填写的数据。 编辑网格中的数据,并通过连接其他一些调用tableadapter.Update(..)的按钮来保存它。 当您将网格拖放到表单(数据源窗口之外)时,您甚至通常会默认获得一个可爱的网格,嵌入在名为 BindingNavigator 的工具栏中

记住; 远离 OleDbCommand; 你绝对不需要它,永远。 您可以使用上面显示的向导将您需要的所有查询添加到 tableadapter。 它更快、更安全; 您在 oledbcommand 中编写的查询极有可能遭受 SQL 注入黑客攻击和编写这样的 SQL 有一天可能会让您被解雇。 将查询写入 tableadapter 向导可确保它们以安全的方式内置到您的 tableadapter 中,不会受到黑客攻击

有一天,您可能会从数据集和表格适配器转向实体框架,但这是一个很好的介绍,只是有点陡峭的学习曲线。

哦,安装 VS2019,即使只有在您的个人计算机上(如果有); 相比之下,2008 年是一次可怕的经历(我认为它甚至不能与 .NET 4 一起使用。)

*实际上,表单设计器通常所做的是将绑定源绑定到数据表,然后将网格绑定到绑定源,但我现在将忽略它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM