Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Classe SqlBulkCopy

A plataforma .NET permite implementar de uma forma muito simples um BULK INSERT em uma base de dados SQL, ou seja, importar dados de uma fonte de dados (base de dados, arquivo de texto, XML, etc) e gravar numa tabela SQL. Este método é muito prático e com ganhos significativos em termos de eficiência para diversas operações como a migração de dados, inserção de muita informação, etc. Esta operação também é possível de se fazer, e para não é familiar com o termo BULK INSERT, utilizando comandos Transact-SQL.

Para mostrar como utilizar a classe SqlBulkCopy, e como pode ser útil, será mostrado um pequeno exemplo de migração de dados de Access para SQL.

Deve-se verificar se o mapeamento entre colunas está correcto (podem-se utilizar os nomes da colunas em vez do seu índice) e se o tipo de dados das colunas de origem é ser suportado nas colunas de destino (não gravar strings em integers por exemplo). Podem ser utilizadas apenas algumas colunas.

O que o seguinte código faz é ler a informação de uma tabela de Access para um DataSet (que ficará numa DataTable) e depois, usando o SqlBulkCopy, gravar essa informação na tabela de destino no SQL.

Lê a informação do Access, da tabela tblOrigem:

        Dim connStringAccess As String = _
            "Provider=Microsoft.Jet.OLEDB.4.0;" & _
            "Data Source=c:\DadosOrigem.mdb;" & _
            "Jet OLEDB:Database Password=teste;"

        ' Lê a informação da tabela do Access para um DataSet
        Dim ds As New DataSet
        Dim SQL As String = "SELECT * FROM tblOrigem"
        Using da As New OleDb.OleDbDataAdapter(SQL, connStringAccess)
            da.Fill(ds)
        End Using

Grava no SQL, na tabela tblDestino, com base na informação anterior:

        Dim connStringSQL As String = _
            "Data Source=<Servidor>;" & _
            "Integrated Security=False;" & _
            "User ID=teste;Password=teste"

        ' Cria uma ligação ao servidor SQL
        Using conn As New SqlClient.SqlConnection(connStringSQL)
            conn.Open()

            Using copy As New SqlClient.SqlBulkCopy(conn)

                ' Irá mostrar o total de registos copiados
                AddHandler copy.SqlRowsCopied, AddressOf SqlRowsCopiedEvent

                ' Faz o mapeamento das tabelas em que, por  
                ' exemplo, a coluna 2 da tabela de origem irá   
                ' ser escrita na coluna 3 da tabela de destino
                copy.ColumnMappings.Add(0, 0)
                copy.ColumnMappings.Add(1, 1)
                copy.ColumnMappings.Add(2, 3)
                copy.ColumnMappings.Add(3, 2)

                ' Indica a tabela de destino
                copy.DestinationTableName = "tblDestino"

                Try

                    ' Escreve no SQL
                    copy.WriteToServer(ds.Tables(0))

                Catch ex As Exception
                    MessageBox.Show(ex.Message)
                End Try

            End Using
        End Using

Finalmente a informação do total de registos copiados:

    Sub SqlRowsCopiedEvent(ByVal sender As Object, _
                       ByVal e As System.Data.SqlClient.SqlRowsCopiedEventArgs)

        MessageBox.Show("Registos copiados: " & e.RowsCopied.ToString)

    End Sub

Neste caso o número de registo que irá mostrar será o total, porque não foi definido um BatchSize (que indica o número de registos que irá copiar). Definindo um BatchSize (por exemplo copy.BatchSize = 100), poder-se-ia utilizar este evento para animar uma ProgressBar e mostrar a evolução do processo, sendo obviamente, o processo um pouco mais lento desta forma.

Nota: Como curiosidade, e numa migração recente em que utilizei este método, a migração de uma tabela de Access com 260.000 registo para SQL, demorou aproximadamente 6 segundos.

Mas esta classe pode ter mais aplicação, como por exemplo, inserir no SQL um grande número de registo. Pode-se criar uma tabela, carregar os dados e finalmente inserir todos os registos de uma vez (sem várias chamadas à base de dados).

Por exemplo:

        Dim dt As New DataTable("Origem")
        dt.Columns.Add("ID", GetType(Integer)).AutoIncrement = True
        dt.Columns.Add("numero", GetType(Integer))
        dt.Columns.Add("nome", GetType(String))
        dt.Columns.Add("data", GetType(DateTime))

        Dim dr As DataRow = dt.NewRow
        dr.Item("numero") = 1
        dr.Item("nome") = "Jorge Paulino"
        dr.Item("data") = DateTime.Now
        dt.Rows.Add(dr)

        Dim ds As New DataSet
        ds.Tables.Add(dt)


E depois repetir o mapeamento e a inserção usando a classe SqlBulkCopy.

Espero que ajude!

6 comentários:

Nuno disse...

Bem, quando não se sabe, não se sabe. Ando eu há algum tempo à procura duma cena deste tipo para migrar uma base de dados inteira de Access para SQL e não tinha conhecimento desta classe.

Acho que ainda tenho que investigar um pouco mais, mas isto já ajuda imenso.

Obrigado pela dica!

Henrry Pires disse...

hehe e eu que a tempos precisei disto, bem fica para a próxima

Tks

Anónimo disse...

Boas JPaulino

Diz-me uma coisa, como é o Provider para poder ler de um ficheiro texto?
No exemplo tem de access para sql, e como poderia fazer de texto para SQL?

Cpts
SLIFE

Jorge Paulino disse...

@SLIFE,

Vê aqui: http://www.portugal-a-programar.org/forum/index.php/topic,43481.msg327270.html#msg327270

Anónimo disse...

Aqui está o link para o Visual Basic 4.0 Enterprise:

http://bitshare.com/?f=bpr2idj8

Aqui está o link para baixar o Visual Basic 5.0 Professional:

http://bitshare.com/?f=ajhw437d

Exemplos de programas feitos em Visual Basic (todas as versões):

http://bitshare.com/?f=5o47ucxl

Obrigado!

Anónimo disse...

Exemplos de programas em Visual Basic (todas as versões) - 100% compilado em P-code:

http://bitshare.com/?f=dqk1qxrp

Hoje em dia, não faz muita diferença de velocidade de execução entre um programa executável compilado em código nativo e um compilado em P-Code, porque os processadores de hoje são super-velozes, podendo ter 1 ou mais núcleos e trabalham na arquitetura de 64 BITS... Neste caso, não vai sentir a diferença.

Mensagens Recentes



Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico