Atualização em lote do Microsoft Access via ADO.Net e interoperabilidade COM

Esta é uma espécie de follow-up paraesta discussão. Tudo isso é com.Net 2.0; para mim, pelo menos.

Essencialmente, Marc (OP de cima) tentou várias abordagens diferentes para atualizar uma tabela do MS Access com 100.000 registros e descobriu que usar uma conexão DAO era mais ou menos10 a 30x mais rápido do que usando ADO.Net. Eu caí praticamente no mesmo caminho (exemplos abaixo) e cheguei à mesma conclusão.

Eu acho que estou apenas tentando entenderporque OleDB e ODBC são muito mais lentos e adoraria saber se alguém encontrou uma resposta melhor do que DAO desde esse post em 2011. Eu realmente preferiria evitar o DAO e / ou Automation, já que eles exigirão do cliente máquina para ter acesso ou o mecanismo de banco de dados redistribuível (ou eu estou preso com o DAO 3.6 que não oferece suporte a .ACCDB).

Tentativa original; ~ 100 segundos para 100.000 registros / 10 colunas:

Dim accessDB As New OleDb.OleDbConnection( _ 
                      "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
                                accessPath & ";Persist Security Info=True;")
accessDB.Open()

Dim accessCommand As OleDb.OleDbCommand = accessDB.CreateCommand
Dim accessDataAdapter As New OleDb.OleDbDataAdapter( _
                                   "SELECT * FROM " & tableName, accessDB)
Dim accessCommandBuilder As New OleDb.OleDbCommandBuilder(accessDataAdapter)

Dim accessDataTable As New DataTable
accessDataTable.Load(_Reader, System.Data.LoadOption.Upsert)

//This command is what takes 99% of the runtime; loops through each row and runs 
//the update command that is built by the command builder. The problem seems to 
//be that you can't change the UpdateBatchSize property with MS Access
accessDataAdapter.Update(accessDataTable)

Enfim, achei isso muito estranho, então experimentei vários sabores da mesma coisa:

Desligando OleDB para ODBCLooping através da tabela de dados e executando uma instrução INSERT para cada linhaIsto é o que .Update faz de qualquer maneiraUsando o provedor ACE em vez de Jet (ODBC e OleDB)Executando a atualização do adaptador de dados de dentro do loop DataReader.ReadFora de frustração; foi hilário.

Finalmente, tentei usar o DAO. O código deve basicamente estar fazendo a mesma coisa; exceto que claramente não é, porque isso é executado em ~ 10 segundos.

 Dim dbEngine As New DAO.DBEngine
 Dim accessDB As DAO.Database = dbEngine.OpenDatabase(accessPath)
 Dim accessTable As DAO.Recordset = accessDB.OpenRecordset(tableName)

While _Reader.Read
    accessTable.AddNew()
      For i = 0 To _Reader.FieldCount - 1
        accessTable.Fields(i).Value = _Reader.Item(i).ToString
      Next
    accessTable.Update()
End While

Algumas outras notas:

Tudo é convertido em Strings em todos os exemplos para tentar manter as coisas o mais simples e consistente possívelExceção: No meu primeiro exemplo, usando a função Table.Load, eu não sei porque ... bem, eu realmente não posso, mas fiz basicamente a mesma coisa quando passei pelo leitor e criei comandos de inserção (que é o que está fazendo, de qualquer maneira). Isso não ajudou.Para cada campo ... Próximo vs. Campo (i) vs. Campo (nome) não fez diferença para mimTodos os testes que executei começaram com uma tabela de dados vazia e pré-construída em um banco de dados do Access recém-compactadoCarregar o Leitor de Dados em uma Tabela de Dados na memória leva ~ 3 segundosEu não acho que é um problema com o empacotamento dos dados, porque o post de Marc indicou que carregar um arquivo de texto via automação é tão rápido quanto o DAO - se é que não deveria empacotar os dados ao usar ODBC / OleDB, masdevemos ao usar a automaçãoTudo isso me incomoda muito mais do que deveria, porque não faz sentido

Espero que alguém possa esclarecer isso ... é apenas estranho. Desde já, obrigado!

questionAnswers(2)

yourAnswerToTheQuestion