當添加一個數據文件時,例如MDB或ACCDB,您的項目,它成爲一個源文件。當您在調試器中運行項目時,您的應用程序不會連接到該數據庫。當您構建時,該源數據文件將與您的EXE一起復制到輸出文件夾,並且它是您在運行時連接的副本。如果你在源文件中查找測試期間添加的任何數據,當然你不會找到它。
當你考慮它時,這是非常有意義的。當需要部署應用程序時,您是否真的需要花時間清理數據庫,將其置於適合分發的狀態?通過對副本進行測試,可以使源數據庫保持原始狀態。當您構建應用程序的發行版時,乾淨的源數據庫將使用EXE複製到發行版輸出文件夾中,並且您的用戶將獲得該乾淨的副本。
現在,將數據庫添加到項目時,默認情況下,其Copy to Output Directory
屬性設置爲Copy always
。這意味着每次構建項目時都會創建一個新副本。如果運行項目並對數據庫進行更改,則停止調試程序,更改代碼並再次運行項目,重建項目並創建新的數據庫副本,從而使更改消失。如果您在不對代碼進行任何更改的情況下運行該項目兩次,那麼將不會再次構建它,以免重寫工作數據庫中的更改。
您應該做什麼 - 以及我認爲Microsoft應該默認完成的操作 - 將Copy to Output Directory
屬性更改爲Copy if newer
。這樣,即使您的項目已建好,除非您對源數據庫進行了更改,否則不會創建新的數據庫副本。這將允許您保持相同的測試數據在您的工作數據庫中,只要您想要。當您確實想重新開始時,只需手動從輸出文件夾中刪除數據文件或更改Copy to Output Directory
即可獲得單個版本。
由於源文件可能會更改,即使您不更改其中包含的數據或模式,Microsoft也會對此提出警告。簡單地打開文件會影響它,並提示新的副本覆蓋你的工作目錄。如果每次都會創建一個新副本,我會說大吶。當我不打算這樣做時,我很少看到數據文件更新。您可以read here瞭解更多信息。
現在,關於ID,當您添加新行時,您的DataTable
將創建一個臨時ID。只要您在應用程序中使用數據而不將其提交到數據庫,該ID就可以用於識別該行,甚至可以識別相關的子行。當您提交更改時,數據庫會生成一個永久ID。
通常情況下,您不需要那個ID就可以了,因爲您不會那時使用數據。如果不再次檢索數據,您將不會再使用這些數據,在這種情況下,您將使用它檢索最終的ID。有時候,你確實想要立即檢索最終的ID。其中一個必要的場景是保存父記錄和一個或多個子記錄的位置。保存父記錄時,您需要從數據庫獲取最終的ID並將其放回DataTable
,以便在保存子行之前更新子行中的外鍵值。如果你沒有這樣保存子行,那麼你將違反數據庫中的外鍵約束,並拋出一個異常。
一些數據提供者,例如,用於SQL Server的SqlClient
,每個命令支持多個SQL語句。在這種情況下,您可以簡單地在INSERT
聲明後添加SELECT
聲明,並且無需額外代碼即可將新ID恢復到DataTable
中。不幸的是,Jet和ACE OLE DB提供程序不支持每個命令的多個SQL語句。因此,當插入記錄時,你必須寫一些代碼來明確地檢索新的ID。這裏是你如何能做到與類型化的DataSet的快速代碼示例:
''' <summary>
''' Handles the RowUpdated event of the parent adapter.
''' </summary>
''' <param name="sender">
''' The adapter that saved the row.
''' </param>
''' <param name="e">
''' The data for the event.
''' </param>
''' <remarks>
''' This event handler is used to retrieve an auto-generated ID from the database after a row is inserted and update the corresponding row in the local data set.
''' </remarks>
Private Sub parentAdapter_RowUpdated(sender As Object, e As OleDbRowUpdatedEventArgs)
'We are only interested in new records.
If e.StatementType = StatementType.Insert Then
'Get the last ID auto-generated by the database.
Dim lastAutoNumber = Me.parentAdapter.GetLastAutoNumber().Value
'Update the ID of the local row.
DirectCast(e.Row, ParentChildDataSet.ParentRow).ParentID = lastAutoNumber
End If
End Sub
在這種情況下,GetLastAutoNumber
是我加入到DataSet設計的表適配器查詢。這是一個標量查詢簡單地包含以下SQL:
SELECT @@IDENTITY
你可以找到完整的示例here。
那麼你期望發生什麼,實際發生了什麼?我不會去YouTube找出你可以在這裏解釋的。 – jmcilhinney
@jmcilhinney我想使用2個文本框和ADD&SAVE按鈕將數據插入到MS Access表中...... 但是我得到了-1的值,並且數據無法保存在MS Access表中。 – user3822131
-1是由'DataTable'生成的臨時ID。最終的ID由數據庫在保存數據時生成。你怎麼知道數據無法保存?無論是保存還是拋出異常。如果拋出異常,那麼錯誤信息是什麼?如果沒有例外,那麼數據將被保存。 – jmcilhinney