问题
Already have the DataTable populated but need to dump its entire table contents into an Access database.
Using (conn)
If conn.State <> ConnectionState.Open Then conn.Open()
Dim adapter As OleDbDataAdapter = New OleDbDataAdapter("SELECT * FROM " & sMdbTableName, conn)
adapter.InsertCommand = New OleDbCommand("INSERT INTO " & sMdbTableName & " SELECT * FROM " & sMdbTableNameSource & ";", conn)
adapter.TableMappings.Add(sMdbTableName, ds.Tables.Item(sMdbTableNameSource).ToString)
adapter.Update(ds.Tables.Item(sMdbTableNameSource))
End Using
Im trying to do something like this but no errors and no data added. Need the best performing way.
Thanks
Edit:
Updated code is slow as heck and need a bulk type of access import:
Using (conn)
If conn.State <> ConnectionState.Open Then conn.Open()
Dim adapter As OleDbDataAdapter = New OleDbDataAdapter()
adapter.InsertCommand = New OleDbCommand("INSERT INTO " & sMdbTableName & "(Field1, Field2, Field3, Field4, Field5) VALUES(@Field1, @Field2, @Field3, @Field4, @Field5);", conn)
adapter.InsertCommand.Parameters.Add("Field1", OleDbType.VarChar, 16, "Field1")
adapter.InsertCommand.Parameters.Add("Field2", OleDbType.VarChar, 16, "Field2")
adapter.InsertCommand.Parameters.Add("Field3", OleDbType.VarChar, 16, "Field3")
adapter.InsertCommand.Parameters.Add("Field4", OleDbType.VarChar, 16, "Field4")
adapter.InsertCommand.Parameters.Add("Field5", OleDbType.VarChar, 16, "Field5")
adapter.TableMappings.Add(sMdbTableName, ds.Tables.Item(sMdbTableNameSource).ToString)
adapter.Update(ds.Tables.Item(sMdbTableNameSource))
End Using
回答1:
The problem is that the RowState
of every DataRow
in your DataTable
will be Unchanged
and therefore they will be ignored when you call Update
. If you want to insert those rows then their RowState
must be Added
. You can make that happen by setting the AcceptChangesDuringFill
property of the data adapter to False
before calling Fill
. That will prevent AcceptChanges
being called after the DataTable
is populated, which is what changes the RowState
properties from Added
to Unchanged
. If that's not an option then you must loop through the rows and call SetAdded
on each one.
回答2:
Private Sub CopyDatatableToAccess(dt As DataTable, AccsessAddress As String, TableName As String)
Try
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & AccsessAddress & ";Persist Security Info=False;"
Dim accConnection As New OleDb.OleDbConnection(connString)
Dim selectCommand As String = "SELECT <field1>, <field2> and so on FROM <table>" & TableName
Dim accDataAdapter As New OleDb.OleDbDataAdapter(selectCommand, accConnection)
Dim accCommandBuilder As New OleDb.OleDbCommandBuilder()
accDataAdapter.InsertCommand = accCommandBuilder.GetInsertCommand()
accDataAdapter.UpdateCommand = accCommandBuilder.GetUpdateCommand()
Dim accDataTable As DataTable = dt.Copy()
''Just to make sure, set the RowState to added to make sure an Insert is performed'
For Each row As DataRow In accDataTable.Rows '
If row.RowState = DataRowState.Added Or DataRowState.Unchanged Then '
row.SetAdded() '
End If '
Next '
accDataAdapter.Update(accDataTable)
Catch ex As Exception
End Try
End Sub
回答3:
DataTables essentially use all row-by-row processing.
So if you need to do a push from your .net code into Access, looping through the table rows and running a simple Update statement using the values from the row - in a separate command - is not the worst thing.
The Insert/Update "statements" in the DataTable will result in the same behavior. So if you're tired and can't get them to work, you can bail out to a separate Update :).
If you were going to SQLServer, the SQLBulkCopy object would be perfect and should be faster. Unfortunately, I'm not aware of an object like that for Access.
That would be what to search for.
来源:https://stackoverflow.com/questions/24152126/bulk-insert-from-datatable-to-access-database