Vb.net 从DataTable到Access数据库的大容量插入

Vb.net 从DataTable到Access数据库的大容量插入,vb.net,ms-access,Vb.net,Ms Access,已填充DataTable,但需要将其整个表内容转储到Access数据库中 Using (conn) If conn.State <> ConnectionState.Open Then conn.Open() Dim adapter As OleDbDataAdapter = New OleDbDataAdapter("SELECT * FROM " & sMdbTableName, conn) adapter.InsertCommand = New

已填充DataTable,但需要将其整个表内容转储到Access数据库中

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
使用(连接)
如果连接状态连接状态打开,则连接打开()
作为OleDbDataAdapter的Dim适配器=新OleDbDataAdapter(“选择*自”&sMdbTableName,conn)
adapter.InsertCommand=新的OleDbCommand(“插入到”&sMdbTableName&“选择来自”&sMdbTableNameSource&“;”,conn)
adapter.TableMappings.Add(sMdbTableName,ds.Tables.Item(sMdbTableNameSource.ToString)
adapter.Update(ds.Tables.Item(sMdbTableNameSource))
终端使用
我正在尝试这样做,但没有错误,也没有添加数据。需要最好的表演方式

谢谢

编辑:

更新的代码速度很慢,需要批量访问导入:

        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
使用(连接)
如果连接状态连接状态打开,则连接打开()
作为OleDbDataAdapter的Dim适配器=新OleDbDataAdapter()
adapter.InsertCommand=新的OleDbCommand(“插入到”&sMdbTableName&“(字段1,字段2,字段3,字段4,字段5)值(@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))
终端使用

问题在于
数据表中每个
数据行的
行状态
保持不变
,因此在调用
更新
时将忽略它们。如果要插入这些行,则必须添加它们的
RowState
。在调用
Fill
之前,可以通过将数据适配器的
AcceptChangesDuringFill
属性设置为
False
来实现这一点。这将防止在填充
数据表后调用
AcceptChanges
,这将
RowState
属性从
Added
更改为
Unchanged
。如果这不是一个选项,那么您必须在各行之间循环,并对每一行调用
SetAdded

数据表基本上使用所有逐行处理

因此,如果需要将.net代码推送到Access中,在表行中循环并使用行中的值运行简单的Update语句(在单独的命令中)并不是最糟糕的事情

DataTable中的Insert/Update“语句”将导致相同的行为。因此,如果您很累,无法让他们工作,您可以退出到一个单独的更新:)

如果您要使用SQLServer,SQLBulkCopy对象将是完美的,并且应该更快。不幸的是,我不知道有这样的对象可以访问。
这就是要搜索的内容。

私有子副本数据表访问(dt作为数据表,ACCSESSADRESS作为字符串,TableName作为字符串)
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
尝试 Dim connString As String=“Provider=Microsoft.ACE.OLEDB.12.0;Data Source=“&accessaddress&”Persist Security Info=False;” 作为新OleDb.OleDb连接的Dim accConnection(连接字符串) Dim selectCommand作为String=“SELECT,依此类推从”&TableName Dim accDataAdapter作为新的OleDb.OleDbDataAdapter(选择命令,accConnection) Dim accCommandBuilder作为新的OleDb.OleDbCommandBuilder() accDataAdapter.InsertCommand=accCommandBuilder.GetInsertCommand() accDataAdapter.UpdateCommand=accCommandBuilder.GetUpdateCommand() Dim accDataTable As DataTable=dt.Copy() ''为了确保,将RowState设置为added以确保执行插入' 将每行作为accDataTable.Rows中的DataRow 如果row.RowState=DataRowState.Added或DataRowState.Unchanged,则' row.SetAdded() 结束 下一个 accDataAdapter.Update(accDataTable) 特例 结束尝试 端接头
感谢您的快速回复。我更改了da并重新测试了它,但仍然是同一个问题。今天我的精神被灼伤了,但我认为我的sql语句现在可能不准确。DataTable是“[CodeSource]”,要在db中创建的表是“[Code]”。在变量名称中也有反映。清新的早晨和清新的头脑有助于创造奇迹lol。我找到了我错过设置AcceptChangesDuringFill的地方,并将插入更改为参数化插入,但速度异常缓慢。我有大约1000000条记录要导入,虽然我们有SQL server,但我不能真正使用它。噢,哇。1mil的访问量很大。。。。我一直认为成千上万的人会遇到麻烦,准备升级。你知道现在可以在生产中正式使用免费的SQL Express,对吗?由于项目限制和客户端运行程序的方式,我们不能使用SQL Server,我们也有SQL Server。此外,在这个论坛上,人们通常不赞成用SQLCECode代替Access。请编辑您的答案,包括您的代码的作用以及它如何解决OP的问题的解释。