Was ist der Unterschied zwischen null und System.DBNull.Value?

91

Gibt es einen Unterschied zwischen null und System.DBNull.Value? Wenn ja, was ist das?

Ich habe dieses Verhalten jetzt bemerkt -

while (rdr.Read())
{
    if (rdr["Id"] != null) //if (rdr["Id"] != System.DBNull.Value)  
    {
        int x = Convert.ToInt32(rdr["Id"]);
    }
}

Während ich Daten mit einem SQL-Datenleser aus der Datenbank abrufe, wird kein zurückgegebener Wert if(rdr["Id"] != null)zurückgegeben trueund schließlich eine Ausnahme für das Umwandeln einer Null als Ganzzahl ausgelöst .

Aber dies, wenn ich if (rdr["Id"] != System.DBNull.Value)Retouren verwende false.

Was ist der Unterschied zwischen null und System.DBNull.Value?

gepflastert
quelle
Nun, sie haben nichts miteinander zu tun. Eine ist eine statische Instanz einer Klasse in System.Data, und die andere ist ein spezieller Wert, der das Fehlen eines Referenten anzeigt. Sie haben nichts miteinander zu tun. Können Sie näher erläutern, worüber Sie verwirrt sind? Ist Ihre eigentliche Frage : „Warum tun DataRowsund DataReaderssetzen DBNull.Valueinnerhalb von sich selbst statt null?“
mqp
Nun, mein Anfang war es nicht, aber nachdem ich von dem gelernt habe, was du gesagt hast, bin ich neugierig. Können Sie mir sagen, warum DataRows und DataReaders DBNull.Value anstelle von null in sich selbst setzen?
Pavanred
Ich bin mir nicht sicher. Hier ist eine Antwort: stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull/… Es ist auch möglich, dass es schwieriger gewesen wäre, damit umzugehen , bevor es in C # nullbare Werttypen gabnull .
mqp
1
Ich hatte hier eine Antwort, aber mir wurde klar, dass sie besser für stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull geeignet ist - also habe ich sie verschoben
Marc Gravell

Antworten:

115

Nun, nullist keine Instanz irgendeiner Art. Es ist vielmehr eine ungültige Referenz.

Ist System.DbNull.Valuejedoch ein gültiger Verweis auf eine Instanz von System.DbNull( System.DbNullist ein Singleton und System.DbNull.Valuegibt Ihnen einen Verweis auf die einzelne Instanz dieser Klasse), die nicht vorhandene * Werte in der Datenbank darstellt.

* Wir würden normalerweise sagen null, aber ich möchte das Problem nicht verwechseln.

Es gibt also einen großen konzeptionellen Unterschied zwischen den beiden. Das Schlüsselwort nullrepräsentiert eine ungültige Referenz. Die Klasse System.DbNullrepräsentiert einen nicht vorhandenen Wert in einem Datenbankfeld. Im Allgemeinen sollten wir vermeiden, dasselbe (in diesem Fall null) zu verwenden, um zwei sehr unterschiedliche Konzepte darzustellen (in diesem Fall eine ungültige Referenz gegenüber einem nicht vorhandenen Wert in einem Datenbankfeld).

Denken Sie daran, aus diesem Grund befürworten viele Leute die Verwendung des Nullobjektmusters im Allgemeinen, was genau System.DbNullein Beispiel dafür ist.

Jason
quelle
43
+1 Ein praktisches Beispiel: Wenn Sie verwenden IDbCommand.ExecuteScalar(), kann es entweder null zurückgeben (keine Datensätze zurückgegeben) oder DbNull(die erste Spalte im ersten Datensatz ist ein 'nicht vorhandener Wert'). Ohne DbNullSie könnten Sie nicht voneinander unterscheiden.
C.Evenhuis
Ich würde dringend empfehlen, eine Sprache zu verwenden, die die Verwendung von Null verbietet und dies zu absolut 0 zusätzlichen Kosten. Das Leben ist zu kurz für "Null-Objekt-Muster"
Nicole
3
Eine Nullreferenz ist vollkommen gültig. ☺
IllidanS4 will Monica
21

Aus der Dokumentation der DBNull-Klasse :

Verwechseln Sie den Begriff Null in einer objektorientierten Programmiersprache nicht mit einem DBNull-Objekt. In einer objektorientierten Programmiersprache bedeutet null das Fehlen eines Verweises auf ein Objekt. DBNull repräsentiert eine nicht initialisierte Variante oder nicht vorhandene Datenbankspalte.

Heinzi
quelle
11

DBNull.Value ist ärgerlich, damit umgehen zu müssen.

Ich verwende statische Methoden, die prüfen, ob es DBNull ist, und dann den Wert zurückgeben.

SqlDataReader r = ...;
String firstName = getString(r[COL_Firstname]);

private static String getString(Object o) {
   if (o == DBNull.Value) return null;
   return (String) o;
}

Wenn Sie Werte in eine DataRow einfügen, können Sie "null" nicht verwenden. Sie müssen DBNull.Value verwenden.

Zwei Darstellungen von "null" zu haben, ist ein schlechtes Design ohne offensichtlichen Nutzen.

Abscheu
quelle
2
Das Gefühl des Ekels, das wir teilen, bezüglich: Ihre letzte Aussage wird nur durch die Ironie
übertroffen, hier aufzutauchen
5

DBNull.Value wird von den .NET-Datenbankanbietern zurückgegeben, um einen Nulleintrag in der Datenbank darzustellen. DBNull.Value ist nicht null und der Vergleich mit null für Spaltenwerte, die aus einer Datenbankzeile abgerufen werden, funktioniert nicht. Sie sollten immer mit DBNull.Value vergleichen.

http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx

James Michael Hare
quelle
ps Sie sollten auch DBNull.Value verwenden, um einen Nullparameter an die Datenbank zu übergeben. Andernfalls wird er möglicherweise interpretiert, da der Parameter nicht übergeben wurde.
James Michael Hare
1
DBNull ist nicht "was die Datenbank zurückgibt" - es ist einfach, wie ADO.NET es interpretiert; Ich persönlich bin mir nicht sicher, ob diese Interpretation sehr wertvoll ist
Marc Gravell
@MarcGravell Ja, Marc, du bist richtig. Ich habe das falsch formuliert. ASP.NET übersetzt den Nullspaltenwert der Datenbank in DBNull.Value
James Michael Hare
3

DataRow verfügt über eine Methode, mit IsNull()der Sie die Spalte testen können, wenn sie einen Nullwert hat - in Bezug auf die Null, wie sie von der Datenbank gesehen wird.

DataRow["col"]==nullwird immer sein false.

verwenden

DataRow r;
if (r.IsNull("col")) ...

stattdessen.

Daniel Mošmondor
quelle
3

Null ähnelt dem Nullzeiger in C ++ . Es ist also eine Referenz, die auf keinen Wert verweist .

DBNull.Valueist völlig anders und ist eine Konstante, die zurückgegeben wird, wenn ein Feldwert NULL enthält.

Aliostad
quelle