Я пытаюсь вставить много записей в базу данных Jet (Access) через ADO.NET / OleDb.Работает мучительно медленно.Медлительность в основном связана с методом DbDataAdapter.Update
.По словам Microsoft,
... эти операторы не выполняются как пакетный процесс;каждая строка обновляется индивидуально.
Это настоящий WTF, поскольку моя база данных дает производительность примерно в 30 раз медленнее, чем эквивалентный код в VB6, использующий старый ADO или DAO (набор записей с AddNew
/Update
loop).
Поставщик SqlClient имеет класс SqlBulkCopy
;Есть ли что-нибудь эквивалентное для OleDb?
Даже возможность изменить поведение кэширования записи может помочь.(т.е. не очищайте кеш после вставки каждой строки!)
Могу ли я что-нибудь сделать, или ADO.NET просто не работает для Jet?
* Отредактировано: Вот урезанная версия моего кода с использованием урезанной тестовой базы данных.
Во-первых, версия VBA / ADO (Access 2003):
Dim con As ADODB.Connection
Set con = CurrentProject.Connection
con.Execute "DELETE * FROM tblTest", , adCmdText Or adExecuteNoRecords
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.Open "tblTest", con, , adLockPessimistic
Dim i&, t!
t = Timer
For i = 1 To 10000
rs.AddNew
rs!mainKey = i
rs!testColumn = Rnd * 100
rs.Update
Next
rs.Close
Debug.Print "time to add 10000 (by ADO) " & Timer - t
Вывод: time to add 10000 (by ADO) 0.296875
Теперь версия ADO.NET (VB.NET 2010):
Dim sProvider As String = "PROVIDER = Microsoft.Jet.OLEDB.4.0;"
Dim sDataSource As String = "Data Source = 'C:\test.mdb'"
Dim connection As New OleDbConnection(sProvider & sDataSource)
connection.Open()
Dim q As New OleDbCommand("DELETE * FROM tblTest", connection)
q.ExecuteNonQuery()
Dim ds As New DataSet
Dim selectCmd As OleDbCommand = connection.CreateCommand()
selectCmd.CommandText = "SELECT * FROM tblTest"
Dim da As New OleDbDataAdapter(selectCmd)
da.Fill(ds, "tblTest")
Dim theTable As DataTable = ds.Tables("tblTest")
For i As Integer = 1 To 10000
Dim row = theTable.NewRow()
row.Item("mainKey") = i
row.Item("testColumn") = Rnd() * 100
theTable.Rows.Add(row)
Next i
Dim t! : t = Microsoft.VisualBasic.Timer
Dim cb As New OleDbCommandBuilder(da)
da.Update(ds, "tblTest")
Debug.Print("time to add 10000 (by ADO.NET): " & Microsoft.VisualBasic.Timer - t)
connection.Close()
Вывод: time to add 10000 (by ADO.NET): 5.859375