VB.NET DataTable – Erstellen, Füllen, Filtern (2026)

Die VB.NET DataTable speichert tabellarische Daten im Arbeitsspeicher, mit typisierten Spalten, zeilenweisem Zugriff und eingebautem Filtern. Sie ist das Rückgrat der Datenbindung in WinForms und die Brücke zwischen Datenbank und UI-Controls wie dem DataGridView. Dieser Guide behandelt Erstellung, Filtern, Sortieren, Datenbankanbindung und die häufigsten Fehler.

.NET-Hilfe gesucht?

Du baust mehr als einen schnellen Prototyp?

Ich entwickle seit über 17 Jahren professionell in VB.NET und C#. Von Datenschichten bis zur kompletten Desktop-Anwendung kann ich helfen.

Was ist eine DataTable und wann setzt man sie ein?

Eine DataTable liegt im System.Data-Namespace und stellt eine einzelne Tabelle im Arbeitsspeicher dar. Vergleichbar mit einer Tabellenkalkulation: sie hat Spalten mit Namen und Typen, und Zeilen, die die eigentlichen Werte enthalten.

Verwende eine DataTable, wenn:

  • Du tabellarische Daten an ein DataGridView oder andere WinForms-Controls binden willst
  • Du mit ADO.NET arbeitest und eine Tabelle aus einer Datenbankabfrage füllen willst
  • Du eingebautes Filtern und Sortieren brauchst, ohne eigene Logik schreiben zu müssen
  • Du CSV- oder Excel-Importe verarbeitest, bei denen Zeilen und Spalten natürlich abbildbar sind

Falls du nur eine geordnete Liste von Objekten brauchst, ist eine VB.NET List(Of T) einfacher und typsicherer. Für Key-Value-Lookups verwende ein Dictionary. Die DataTable spielt ihre Stärken aus, wenn du eine flexible, schemabasierte Struktur mit Filtern, Sortieren und UI-Binding brauchst.

Eine DataTable mit Spalten erstellen

Jede DataTable beginnt mit einem Schema: den Spalten, die festlegen, welche Daten jede Zeile aufnehmen kann.

Dim table As New DataTable("Contacts")

' Spalten mit Name und Typ hinzufügen
table.Columns.Add("Id", GetType(Integer))
table.Columns.Add("Name", GetType(String))
table.Columns.Add("Email", GetType(String))
table.Columns.Add("Age", GetType(Integer))

' Primärschlüssel setzen
table.PrimaryKey = {table.Columns("Id")}

Jede Spalte hat einen DataType (Integer, String, DateTime, Decimal, Boolean, etc.) und einen optionalen ColumnName. Der Primärschlüssel ermöglicht schnelle Lookups mit Rows.Find() und verhindert doppelte Einträge.

Spalteneigenschaften

' Auto-Increment Spalte
Dim idCol = table.Columns("Id")
idCol.AutoIncrement = True
idCol.AutoIncrementSeed = 1
idCol.AutoIncrementStep = 1

' Standardwert
table.Columns("Age").DefaultValue = 0

' Nullwerte verbieten
table.Columns("Name").AllowDBNull = False

Zeilen hinzufügen

' Methode 1: NewRow + Felder zuweisen
Dim row As DataRow = table.NewRow()
row("Name") = "Alice"
row("Email") = "alice@example.com"
row("Age") = 30
table.Rows.Add(row)

' Methode 2: Werte direkt übergeben (Spaltenreihenfolge)
table.Rows.Add(Nothing, "Bob", "bob@example.com", 25)

' Methode 3: Aus einem Object-Array
Dim values() As Object = {Nothing, "Clara", "clara@example.com", 35}
table.Rows.Add(values)

Bei einer AutoIncrement-Id-Spalte übergibst du Nothing für das Feld. Die DataTable vergibt den nächsten Wert automatisch.

Daten lesen und zugreifen

' Auf eine bestimmte Zeile per Index zugreifen
Dim firstRow As DataRow = table.Rows(0)
Dim name As String = CStr(firstRow("Name"))

' Alle Zeilen durchlaufen
For Each row As DataRow In table.Rows
    Console.WriteLine($"{row("Id")}: {row("Name")} ({row("Email")})")
Next

' Zeile per Primärschlüssel finden
Dim found As DataRow = table.Rows.Find(2)
If found IsNot Nothing Then
    Console.WriteLine($"Gefunden: {found("Name")}")
End If

' Gesamtanzahl der Zeilen
Dim count As Integer = table.Rows.Count

Felder geben Object zurück, daher musst du sie casten (CStr, CInt, CDec, etc.) oder die typisierte Field(Of T)-Erweiterungsmethode verwenden: row.Field(Of String)("Name"). Die Field-Methode behandelt DBNull bei Nullable-Typen automatisch sicher.

Filtern mit Select und DataView

DataTable bietet zwei Wege zum Filtern: die Select()-Methode für schnelle Abfragen und DataView für persistente, bindbare Filter.

DataTable.Select()

' Nach Bedingung filtern
Dim olderThan25() As DataRow = table.Select("Age > 25")

' Filtern + sortieren
Dim sorted() As DataRow = table.Select("Age > 25", "Name ASC")

' Mehrere Bedingungen
Dim specific() As DataRow = table.Select("Age > 20 AND Name LIKE 'A%'")

' Ergebnisse verarbeiten
For Each row In olderThan25
    Console.WriteLine(row("Name"))
Next

Der Filterausdruck nutzt eine SQL-ähnliche Syntax: =, <>, >, <, LIKE, AND, OR, IN, IS NULL. Der Sortierausdruck nimmt einen Spaltennamen gefolgt von ASC oder DESC.

DataView für bindbares Filtern

Eine DataView umschließt eine DataTable und liefert eine gefilterte, sortierte Sicht, die direkt an UI-Controls gebunden werden kann:

Dim view As New DataView(table)
view.RowFilter = "Age >= 30"
view.Sort = "Name ASC"

' An DataGridView binden
DataGridView1.DataSource = view

' Filter zur Laufzeit ändern (UI aktualisiert sich automatisch)
view.RowFilter = "Name LIKE 'B%'"

DataView ist die bessere Wahl für eine DataGridView-Filterfunktion, weil sie das gebundene Control automatisch aktualisiert, wenn RowFilter oder Sort geändert werden.

Projekt in Planung?

Brauchst du eine skalierbare .NET-Datenschicht?

Von DataTables bis zur kompletten Anwendungsarchitektur: Ich entwerfe Software, die hält. Lass uns über dein Projekt sprechen.

Zeilen sortieren

Die DataTable selbst hat keine Sort()-Methode. Sortiert wird über Select() oder DataView:

' Sortieren mit Select (gibt DataRow-Array zurück)
Dim sortedRows() As DataRow = table.Select("", "Age DESC")

' Sortieren mit DataView (bindbar)
Dim view As New DataView(table)
view.Sort = "Name ASC, Age DESC"

' Sortieren mit LINQ (gibt neue Collection zurück)
Dim linqSorted = From row In table.AsEnumerable()
                 Order By row.Field(Of String)("Name")
                 Select row

Für DataGridView-Binding verwende DataView. Zum Verarbeiten von Zeilen im Code funktionieren die Select()-Methode und LINQ gleich gut.

Zeilen aktualisieren und löschen

' Feld aktualisieren
table.Rows(0)("Email") = "alice.new@example.com"

' Per Primärschlüssel aktualisieren
Dim target As DataRow = table.Rows.Find(2)
If target IsNot Nothing Then
    target("Age") = 26
End If

' Zeile löschen (markiert sie als gelöscht)
table.Rows(0).Delete()

' Zeile sofort entfernen
table.Rows.Remove(table.Rows(0))

' Alle ausstehenden Änderungen übernehmen
table.AcceptChanges()

Wichtiger Unterschied: Delete() markiert die Zeile mit RowState = Deleted, behält sie aber in der Tabelle, bis AcceptChanges() aufgerufen wird. Remove() löscht die Zeile sofort. Verwende Delete(), wenn du Change Tracking brauchst (z.B. beim Zurückschreiben in die Datenbank mit einem DataAdapter).

DataTable an ein DataGridView binden

Einer der häufigsten Einsatzzwecke einer DataTable ist die Anzeige in einem DataGridView:

' Direkte Bindung
DataGridView1.DataSource = table

' Bindung über DataView (mit Filter + Sortierung)
Dim view As New DataView(table)
view.RowFilter = "Age > 25"
view.Sort = "Name ASC"
DataGridView1.DataSource = view

Das DataGridView generiert die Spalten automatisch aus dem DataTable-Schema. Änderungen im Grid werden automatisch in die DataTable zurückgeschrieben. Für ein schreibgeschütztes Grid setze DataGridView1.ReadOnly = True.

Grid nach Datenänderungen aktualisieren

' Zeile programmatisch hinzufügen
table.Rows.Add(Nothing, "David", "david@example.com", 28)

' Grid aktualisiert sich automatisch bei gebundener DataTable
' Kein manuelles Refresh nötig

' Wenn du die gesamte DataTable austauschst, binde sie neu
DataGridView1.DataSource = Nothing
DataGridView1.DataSource = newTable

Daten aus einer Datenbank laden

DataTable funktioniert mit jedem ADO.NET-Provider. Hier ein Beispiel mit SQLite:

Imports System.Data.SQLite

Dim table As New DataTable()

Using connection As New SQLiteConnection("Data Source=app.db")
    connection.Open()
    Using command As New SQLiteCommand("SELECT * FROM Contacts", connection)
        Using reader As SQLiteDataReader = command.ExecuteReader()
            table.Load(reader)
        End Using
    End Using
End Using

' table enthält jetzt alle Zeilen der Contacts-Tabelle
DataGridView1.DataSource = table

Die Load()-Methode liest alle Zeilen aus einem DataReader und erstellt die Spalten automatisch anhand des Abfrageergebnisses. Das funktioniert mit SQL Server, MySQL, PostgreSQL und jedem anderen ADO.NET-Provider.

Alternative: DataAdapter verwenden

Dim table As New DataTable()

Using connection As New SQLiteConnection("Data Source=app.db")
    Using adapter As New SQLiteDataAdapter("SELECT * FROM Contacts", connection)
        adapter.Fill(table)
    End Using
End Using

Der DataAdapter-Ansatz ist kürzer und unterstützt auch das Zurückschreiben von Änderungen in die Datenbank mit adapter.Update(table). Für einfacheren, stark typisierten Datenbankzugriff ohne DataTable ist Dapper eine Alternative.

Konvertierung zwischen DataTable und List

Manchmal muss man zwischen einer DataTable und einer typisierten List(Of T) wechseln:

DataTable zu List(Of T)

Public Class Contact
    Public Property Id As Integer
    Public Property Name As String
    Public Property Email As String
    Public Property Age As Integer
End Class

' DataTable-Zeilen in typisierte Liste konvertieren
Dim contacts = table.AsEnumerable().Select(Function(row)
    Return New Contact With {
        .Id = row.Field(Of Integer)("Id"),
        .Name = row.Field(Of String)("Name"),
        .Email = row.Field(Of String)("Email"),
        .Age = row.Field(Of Integer)("Age")
    }
End Function).ToList()

List(Of T) zu DataTable

Public Function ToDataTable(contacts As List(Of Contact)) As DataTable
    Dim table As New DataTable()
    table.Columns.Add("Id", GetType(Integer))
    table.Columns.Add("Name", GetType(String))
    table.Columns.Add("Email", GetType(String))
    table.Columns.Add("Age", GetType(Integer))

    For Each c In contacts
        table.Rows.Add(c.Id, c.Name, c.Email, c.Age)
    Next

    Return table
End Function

Der LINQ-Ansatz mit AsEnumerable() erfordert einen Verweis auf System.Data.DataSetExtensions. Im modernen .NET (5+) ist dieser standardmäßig enthalten.

Häufige Stolperfallen

DBNull ignorieren

DataTable-Felder können DBNull.Value statt Nothing enthalten. Ein direkter Cast wirft dann eine InvalidCastException:

' SCHLECHT - wirft InvalidCastException wenn Email DBNull ist
Dim email As String = CStr(row("Email"))

' GUT - erst auf DBNull prüfen
Dim email As String = If(row.IsNull("Email"), "", CStr(row("Email")))

' OPTIMAL - typisierte Field-Erweiterung verwenden
Dim email As String = row.Field(Of String)("Email")  ' gibt Nothing zurück bei DBNull

Zeilen in einer For-Each-Schleife löschen

Genau wie bei einer List wirft das Ändern einer DataTable während der Iteration eine Exception. Verwende eine rückwärts laufende For-Schleife oder sammle die Zeilen zuerst:

' SCHLECHT - Änderung während Iteration
For Each row As DataRow In table.Rows
    If CInt(row("Age")) < 18 Then
        row.Delete()
    End If
Next

' GUT - rückwärts iterieren
For i As Integer = table.Rows.Count - 1 To 0 Step -1
    If CInt(table.Rows(i)("Age")) < 18 Then
        table.Rows(i).Delete()
    End If
Next
table.AcceptChanges()

AcceptChanges vergessen

Wenn du Delete() auf eine Zeile aufrufst, wird sie nur als gelöscht markiert. Die Zeile erscheint weiterhin in table.Rows.Count und kann unerwartetes Verhalten verursachen. Rufe AcceptChanges() nach einer Reihe von Löschungen auf, oder verwende Remove() für sofortiges Entfernen.

Interessiert?

Erfahrenen .NET-Entwickler gesucht?

Ich übernehme dein Projekt, von sauberen Datenschichten bis zur fertigen Desktop-Anwendung. Schreib mir einfach eine Nachricht.

FAQ

Wie erstelle ich eine DataTable in VB.NET?

Erstelle sie mit Dim table As New DataTable(), füge Spalten hinzu mit table.Columns.Add("Name", GetType(String)) und Zeilen mit table.Rows.Add(werte). Jede Spalte braucht einen Namen und einen Datentyp.

Wie filtere ich eine DataTable in VB.NET?

Verwende table.Select("Age > 25") für schnelle Abfragen, die ein DataRow-Array zurückgeben. Für persistente, bindbare Filter erstelle eine DataView mit view.RowFilter = "Age > 25" und binde sie an dein DataGridView.

Wie binde ich eine DataTable an ein DataGridView?

Setze DataGridView1.DataSource = table. Das Grid generiert die Spalten automatisch aus dem Tabellen-Schema. Für gefilterte Ansichten binde stattdessen eine DataView: DataGridView1.DataSource = New DataView(table).

Was ist der Unterschied zwischen DataTable und List(Of T)?

Eine DataTable speichert untypisierte Zeilen mit Spalten, die zur Laufzeit definiert werden, unterstützt SQL-ähnliches Filtern und bindet nativ an DataGridView. Eine List(Of T) hält stark typisierte Objekte, ist einfacher zu nutzen, erfordert aber manuelles Filtern mit LINQ.

Wie lade ich Datenbankdaten in eine DataTable?

Verwende table.Load(reader) mit einem beliebigen ADO.NET DataReader, oder einen DataAdapter mit adapter.Fill(table). Beide Ansätze erstellen die Spalten automatisch aus dem Abfrageergebnis.

Fazit

Die DataTable ist die richtige Wahl, wenn du schemabasierte, filterbare Tabellendaten mit nativer DataGridView-Bindung brauchst. Verwende Select() für schnelle Abfragen, DataView für live-gefilterte UI-Bindung und Field(Of T) zur sicheren DBNull-Behandlung. Für einfachere Anwendungsfälle mit typisierten Objekten ist eine List(Of T) oft die bessere Wahl. Für Datenbankzugriff ohne DataTable schau dir Dapper an.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Robert Skibbe
Datenschutz-Übersicht

Diese Website verwendet Cookies, damit wir dir die bestmögliche Benutzererfahrung bieten können. Cookie-Informationen werden in deinem Browser gespeichert und führen Funktionen aus, wie das Wiedererkennen von dir, wenn du auf unsere Website zurückkehrst, und hilft unserem Team zu verstehen, welche Abschnitte der Website für dich am interessantesten und nützlichsten sind.