Sử dụng BackgroundWorker cùng SqlBulkCopy trong VB.NET, C#

Như chúng ta đã biết trong .NET FW Microsoft đã thiết kế sẵn 1 class SqlBulkCopy với chức năng để di chuyển dữ liệu từ 1 DB tới 1 DB khác với tốc độ thực thi nhanh.(Chỉ với Sql server)
Nhưng với việc thực hiện chuyển đổi dữ liệu lớn sẽ rất dễ gây ra hiện tượng ứng dụng không thể thực hiện được các thao tác khác vì vậy ta sẽ khắc phục bằng cách sử dụng BackgroundWorker để tiến trình chuyển đổi dữ liệu được thực thi ngầm.
Chúng ta bắt đầu với đoạn code như sau:

Khởi tạo BackgroundWorker
Private WithEvents backgroundWorker As New BackgroundWorker()
BackgroundWorker có 4 event chính:Dispose, DoWork, ProgressChanged, RunWorkerCompleted. Ở đây tôi chỉ sử dụng DoWork và RunWorkerCompleted để thực thi và hiển thị message sau khi hoàn thành tiến trình.
Private Sub backgroundWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
    Handles backgroundWorker.DoWork            
    Try               
        'Khởi tạo connection của database nguồn
        Dim sourceConnection = New SqlConnection("Your source connection string")
        sourceConnection.Open()
        Dim sourceCommand As SqlCommand = New SqlCommand("Your SQL comman", sourceConnection)
        Dim sourceReader = sourceCommand.ExecuteReader()
        'Khởi tạo connection của database đích
        Dim destinationConnection =
                        New SqlConnection("Your destination connection string")
        destinationConnection.Open()
        Using sqlCopy As SqlBulkCopy = New SqlBulkCopy(destinationConnection.ConnectionString)
            sqlCopy.DestinationTableName = input.StrTblName
            sqlCopy.BulkCopyTimeout = 0
            sqlCopy.WriteToServer(sourceReader)            
        End Using
        'Nếu thành công gán result = True để check tại RunWorkerCompleted
        e.Result = True
    Catch ex As Exception
        e.Result = False                
    End Try            
End Sub

Private Sub backgroundWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker.RunWorkerCompleted
    If e.Result Then
        MsgBox("Tiến trình thực hiện xong!!")
    End If
End Sub
Hàm sqlCopy.WriteToServer() có thể dưa param là 1 DataTable, DataSet nhưng để cho tốc độ nhanh nhất vẫn là sử dụng data reader.
Tôi đa test với 2.000.000 record data reader thời gian thực thi ~ 1min, nhưng với data table thời gian mất ~4min.
Khi sử dụng class SqlBulkCopy thường xảy ra lỗi không đúng định dạng dữ liệu giữa DB nguồn và đích dạng như:
The given value of type SqlDecimal from the data source cannot be converted to type decimal of the specified target column.
Ta phải chú ý ép kiểu sao cho đúng và chú ý length của data nữa.
Rất mong được góp ý nếu có sai xót.
First