【问题标题】:Use Multiple DataTables in one DataSet to Insert new records in Access DB在一个数据集中使用多个数据表在 Access DB 中插入新记录
【发布时间】:2012-07-01 08:21:52
【问题描述】:

VB2010 我有一个 DataSet,我添加了多个表,然后我填写这些表,然后将这些记录插入 Access db。

    'create a new DataSet
    Dim dsNav As New DataSet

    'first table
    Dim daTrips As New OleDb.OleDbDataAdapter("SELECT * FROM Trips", connNav)
    daTrips.Fill(dsNav, "Trips")
    Dim cbTrips As New OleDb.OleDbCommandBuilder(daTrips)

   'second table
    Dim daCars = New OleDb.OleDbDataAdapter("SELECT * FROM Cars", connNavDb)
    daCars.Fill(dsNav, "Cars")
    Dim cbCars As New OleDb.OleDbCommandBuilder(daCars)

    'here i open a huge text file and depending on the data i encounter, I create
    'a new DataRow and add it to the appropriate table. i add many new rows to each
    'table. for example
    Dim dsNewRow As DataRow = {tblCars}.NewRow()
    dsNewRow.Item("CarId") = textline.Substring(0, 10)
    dsNewRow.Item("CarMake") = textline.Substring(11, 15)
    tblCars.Rows.Add(dsNewRow)

    'i finish reading the text file and filling up the tables in the one DataSet
    'now i want to insert those records into the Access db
    Dim rowCnt1 As Integer = daTrips.Update(dsNav, "Trips")
    Dim rowCnt2 As Integer = daCars.Update(dsNav, "Cars")

第一次更新有效,但在第二次更新时出现异常:

在 System.Data.dll 中发生了“System.Data.OleDb.OleDbException”类型的第一次机会异常 System.Data.OleDb.OleDbException (0x80040E14):INSERT INTO 语句中的语法错误。 在 System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent,BatchCommandInfo[] batchCommands,Int32 commandCount) 在 System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent,BatchCommandInfo[] batchCommands,Int32 commandCount) 在 System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows,DataTableMapping tableMapping) 在 System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable 数据表,DataTableMapping 表映射) 在 System.Data.Common.DbDataAdapter.Update(DataSet dataSet, String srcTable)

我看过各种文章,他们都建议用一个包含多个 DataTables 的 DataSet 来更新数据库是可行的,但就是不知道为什么会这样。

【问题讨论】:

  • 很难说发生了什么。我将尝试查看 daCars 适配器上插入命令的命令文本是什么。 daCars.InsertCommand.CommandText
  • 所以我在 daTrips.Update 之前添加了一个调试 Debug.Print(daTrips.InsertCommand.CommandText),它抛出了一个异常 System.NullReferenceException。与 UpdateCommand 相同。我根本没有设置这些。我以为 OleDbCommandBuilder 会为您设置这些。
  • Cars 表只包含上面两个字段还是有其他字段?如果存在,您能否显示这些其他字段的名称?
  • 另外,试试这个 - daCars.InsertCommand = cbCars.GetInsertCommand(); 然后看看 InsertCommand.CommandText
  • 再一次,Cars 表定义了主键?如果您希望 commandbuilder 使用更新,表必须有一个主键。

标签: vb.net ms-access datatable dataset oledb


【解决方案1】:

我希望将在 cmets 中发现的所有内容作为答案

  1. 尽量避免在表格中使用保留关键字的字段(以及嵌入空格的字段)
  2. CommandBuilders 需要主键信息,因此添加 adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey 以从 db 架构中恢复主键信息
  3. 对更新使用与填充相同的连接

    Dim dsNav As New DataSet 
    'first table 
    Dim daTrips As New OleDb.OleDbDataAdapter("SELECT * FROM Trips", connNav) 
    daTrips.MissingSchemaAction = MissingSchemaAction.AddWithKey 
    daTrips.Fill(dsNav, "Trips") 
    Dim cbTrips As New OleDb.OleDbCommandBuilder(daTrips) 
    
    'second table 
    Dim daCars = New OleDb.OleDbDataAdapter("SELECT * FROM Cars", connNav) 
    daCars.MissingSchemaAction = MissingSchemaAction.AddWithKey 
    daCars.Fill(dsNav, "Cars") 
    Dim cbCars As New OleDb.OleDbCommandBuilder(daCars) 
    
    'here i open a huge text file and depending on the data i encounter, I create 
    'a new DataRow and add it to the appropriate table. i add many new rows to each 
    'table. for example 
    Dim dsNewRow As DataRow = {tblCars}.NewRow() 
    dsNewRow.Item("CarId") = textline.Substring(0, 10) 
    dsNewRow.Item("CarMake") = textline.Substring(11, 15) 
    tblCars.Rows.Add(dsNewRow) 
    
    'i finish reading the text file and filling up the tables in the one DataSet 
    'now i want to insert those records into the Access db 
    Dim rowCnt1 As Integer = daTrips.Update(dsNav, "Trips") 
    Dim rowCnt2 As Integer = daCars.Update(dsNav, "Cars") 
    

【讨论】:

  • 我还发现字段中的非标准字符会影响更新。你已经提到了空格,但我的几个字段有一个“/”,这也是有问题的。再次感谢。
  • 对于某些(不是全部)字符,您可以通过用方括号将字段名称括起来来解决此问题:[]。但是你需要明确设置命令文本以适应字符。
【解决方案2】:

您在哪里设置dataadapterinsertcommandupdatecommand 属性?

从您的错误来看,dataadapter 似乎正在尝试将记录插入数据库,但 insertcommand 未实例化或未指定值,因此引发了错误。

由于数据适配器通过检查数据表rowstate 中的每一行来决定对.Update 调用执行什么操作,因此您添加到表中的任何行都将尝试使用附加到dataadapterinsertcommand

尝试在您的dataadapters 上设置insertcommandupdatecommand,然后再次尝试运行它,看看会发生什么。

【讨论】:

  • 我没有设置 insertcommand 或 updatecommand 属性。我认为这就是 OleDbCommandBuilder 的目的。
  • 我从来没有亲自使用过命令生成器,我更喜欢手动设置命令,所以我知道它在做什么。如果这就是命令构建器所做的事情,我会感到惊讶,因为它如何知道您的数据库的架构?无论哪种方式,如果您设置插入和更新命令并再次尝试它应该可以正常工作。
猜你喜欢
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
相关资源
最近更新 更多