Wednesday, October 3, 2007

Merge DataTable

. Wednesday, October 3, 2007

Il Framework 2.0 mette a disposizione il metodo Merge fra DataTable che presentano schema differenti, quindi supponendo di avere:

Dim dt1 As DataTable = New DataTable()
Dim idColumn As New DataColumn("ID", GetType(Integer))
dt1.Columns.Add(idColumn)
dt1.Columns.Add(
"Col1", GetType(String))
dt1.Columns.Add(
"Col2", GetType(String))
dt1.Columns.Add(
"Col3", GetType(String))
dt1.Columns.Add(
"Col4", GetType(String))
Dim row1 As DataRow
'Indico la chiave primaria
dt1.PrimaryKey = New DataColumn() {idColumn}

For i As Integer = 0 To 3000
row1
= dt1.NewRow()
row1(
"ID") = i
row1(
"Col1") = "Col1: " + i.ToString()
row1(
"Col2") = "Col2: " + i.ToString()
row1(
"Col3") = "Col3: " + i.ToString()
row1(
"Col4") = "Col4: " + i.ToString()
dt1.Rows.Add(row1)
Next

Dim dt2 As DataTable = New DataTable()
dt2.Columns.Add(
"ID", GetType(Integer))
dt2.Columns.Add(
"Col5", GetType(String))
dt2.Columns.Add(
"Col6", GetType(String))
Dim row2 As DataRow

For i As Integer = 0 To 3000
row2
= dt2.NewRow()
row2(
"ID") = i
row2(
"Col5") = "Col5: " + i.ToString()
row2(
"Col6") = "Col6: " + i.ToString()
dt2.Rows.Add(row2)
Next
'Richiamo il metodo Merge
dt1.Merge(dt2)
otteniamo una DataTable(dt1) composta da 3000 record e 7 colonne(ID, Col1, Col2, Col3, Col4, Col5, Col6).
Ma nel Framework 1.1 è necessario scrivere un metodo ad hoc per ottenere lo stesso risultato.
Dopo una serie di test di perfomarce su alcune soluzioni, la migliore è risultata la seguente:


Private Function MakeDataTaleToHashTable(ByVal dt2 As DataTable, ByVal key As String) As Hashtable
Dim htDt2 As Hashtable = New Hashtable
For Each row As DataRow In dt2.Rows
Dim listColumn As SortedList = New SortedList
For Each col As DataColumn In dt2.Columns
If Not (col.ColumnName = key) Then
listColumn.Add(col.ColumnName, row(col.ColumnName))
End If
Next
htDt2.Add(row(key).ToString(), listColumn)
Next
Return htDt2
End Function

'Esegue il merge fra due DataTable indicando la colonna chiave
Public Sub MergeDataTable(ByRef dt1 As DataTable, ByVal dt2 As DataTable, ByVal key As String)
Dim htDt2 As Hashtable = MakeDataTaleToHashTable(dt2, key)

For Each row As DataRow In dt1.Rows
If (htDt2.ContainsKey(row(key).ToString().Trim())) Then
Dim slColumn As SortedList = htDt2(row(key).ToString().Trim())
For Each keyColumn As String In slColumn.Keys
If Not (dt1.Columns.Contains(keyColumn)) Then
dt1.Columns.Add(
New DataColumn(keyColumn, GetType(String)))
End If
row(keyColumn)
= slColumn(keyColumn)
Next
End If
Next
End Sub
Il metodo principale è MergeDataTable che rihiama il metodo MakeDataTableToHashTable.
Quest'ultimo ha la funzione di "trasformare" la DataTable in una hashTable così formata:
1)key => valore chiave della riga;
2value => un SortedList composto:
  2.1)SortedList key => nome delle colonne
(ad eccezione della colonna chiave);
  2.2)SortdeList value => valore della riga in corrispondenza della colonna aggiunta.
Il metodo MergeDataTable esegue un ciclo su tutte le row della DataTable di destinazione(dt1 nell'esempio) e verifica se il valore della colonna chiave è contenuto nell'hashTable.
In caso affermativo esegue le operazioni di creazione delle nuove colonne e valorizzazione della riga in corrispondenza, recuperando i dati dal SortedList.
Interessante i tempi di esecuzione, nel caso specifico il tutto viene effettuato in 0,031 secondi.

0 commenti:

Post a Comment