Ich hatte das Problem, dass ich mit einem umfangreicher T-SQL Select Statement Daten aus der Datenbank lesen musste und als Resultat einen Vielzahl von Datensätze mit unterschiedlichen Spalten bekommen müsste. Ein Feld mit dem Namen RefID enthielt immer Daten vom Typ integer. Egal was in den anderen Spalten zu dem Datenfeld stand, es sollte immer nur ein Datensatz je RefID ausgegeben werden, doppelte Nummern sollten also verhindert werden. Da T SQL von Haus aus keine Funktion hierfür zur Verfügung stellt (Distinct klappt nur, wenn alle Felddaten gleich sind) suchte ich nach einer Möglichkeit das ganze unter .NET zu lösen und so entstand der Distinct DataTable filter für Visual Basic.
Zunächst wude eine neue Klasse mit dem Namen DataSetHelper angelegt. Die Klasse kann dann so angesprochen werden (in dem Beispiel handelt es sich um ein typisiertes DataSet, welches mit dem Visual Studio Designer angelegt wurde:
Dim datasethelper As New DataSetHelper(Me.DS.NamederTabelle.DataSet)
Me.NamedesTableAdapter.Fill(Me.DS.NamederTabelle)
datasethelper.SelectDistinct("NamederNeuenTabelle", Me.DSquotes.Tables("AlteTabelle"), NameDerSpalte)
Bei Aufruf von SelectDistinct wird zunächst der Name des neuen Tabelle, danach der Quelltabelle und hierauf die Spalte, die geprüft werden soll, angegeben. Darauf hin wird geprüft, ob der vorhandene Inhalt (es können alle möglichen Datenformate übergeben werden) bereits vorkam, falls dies nicht der Fall ist, wird der Inhalt zum DataTable hinzugefügt. Das ganze klappt auch, wenn die Daten unsortiert übermittelt worden.
Klasse:
Public Class DataSetHelper
Public ds As DataSet
Public Sub New(ByRef DataSet As DataSet)
ds = DataSet
End Sub
Public Sub New()
ds = Nothing
End Sub
Private Function ColumnEqual(ByVal A As Object, ByVal B As Object) As Boolean
If A Is DBNull.Value AndAlso B Is DBNull.Value Then
Return True
End If
If A Is DBNull.Value OrElse B Is DBNull.Value Then
Return False
End If
Return (A.Equals(B))
End Function
Public Function SelectDistinct(ByVal TableName As String, ByVal SourceTable As DataTable, ByVal flToCheck As String) As DataTable
Dim dt As DataTable = New DataTable(TableName)
dt.Columns.Add(flToCheck, SourceTable.Columns(flToCheck).DataType)
Dim objToCheck As Object = Nothing
For Each dr As DataRow In SourceTable.Select("", flobjToCheck)
If objToCheck Is Nothing OrElse Not (ColumnEqual(objToCheck, dr(flobjToCheck))) Then
Check = dr(flToCheck)
dt.Rows.Add(New Object() Check})
End If
Next
If Not (ds Is Nothing) Then
ds.Tables.Add(dt)
End If
Return dt
End Function
End Class