DBNULL

Eintrag zuletzt aktualisiert am: 25.08.2023

DBNull repräsentiert eine leere Zelle in einer Datenbank.

.NET-Basisklasse: System.DBNull
https://learn.microsoft.com/de-de/dotnet/api/system.DBNull

Die ADO.NET-Datenzugriffsklassen System.Data.Common.DbDataReader (und die Abkömmlinge wie der SqlDataReader) und System.Data.DataRow (als Teil des DataSet) signalisieren NULL-Spalten in einem Datenbankmanagementsystem nicht als null-Wert in C# bzw. nothing in Visual Basic .NET sondern mit einer Instanz der Klasse System.DBNull.

Zuerst stellt sich die Frage, warum diese beiden Klassen hier diesen Sonderweg gehen. Die Antwort ist (wie so oft): Aus historischen Gründen! Wir erinnern uns an das .NET Framework 1.0 aus dem Jahr 2002. Damals sind die Klassen System.Data.Common.DbDataReader und System.Data.DataSet/System.Data.DataTable/System.Data.DataRow im Rahmen von ADO.NET erstmals erschienen – als Nachfolger des RecordSet aus den klassischen ActiveX Data Objects (ADO).

Damals gab es aber in .NET noch keine Nullable Value Types, also nicht die Struktur System.Nullable<T> und nicht die C#-Typalias mit dem Fragezeichen, also int? für System.Nullable<System.Int32>, bool? für System.Nullable<System.Boolean> und DateTime? für System.Nullable<System.DateTime>. Das bedeutete: Damals konnten ganze und gebrochene Zahlen, Bool-Werte, GUIDs und Zeitangaben noch gar nicht den Wert null besitzen. Der einzige elementare Datentyp, der damals schon den null-Wert annehmen konnte, war System.String. Nullable Values Types wurden erst mit .NET Framework 2.0 eingeführt.

Nun konnten aber relationale Datenbankmanagementsysteme immer schon NULL-Werte in Datenbanken verwalten. Was also tun? Da hat Microsoft sich die Klasse System.DBNull ausgedacht. Die Klassen DbDataReader und DataRow (als Teil von DataSet) liefern in ihrem Indexer immer System.Object zurück. Wenn es einen konkreten Wert gibt, kommt da eine Instanz der Klasse, z.B. für den Spalteninhalt 42 ein System.Int16. Wenn es keinen Wert gibt, kommt eben eine Instanz von System.DBNull.

Da Microsoft damals noch nicht wie heutzutage agil war und daher keine Breaking Changes den Nutzern aufgebürdet hat, blieb es bei der Lösung mit DBNull.

Auch wenn Microsoft inzwischen ja agil ist und Breaking Changes an der Tagesordnung sind bei jeder Hauptversion: Dass die Klassen DbDataReader sowie DataRow DBNull statt Null liefern, gilt auch für die modernsten .NET-Versionen bis hin zum kommenden .NET 8.0. In den moderneren Datenzugriffsbibliotheken wie Entity Framework und Entity Framework Core ist das natürlich mit Nullable Values Types gelöst!