簡體   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