Qual è la differenza tra null e System.DBNull.Value?


92

C'è qualche differenza tra null e System.DBNull.Value? Se sì, che cos'è?

Ho notato questo comportamento ora -

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

Mentre recupero i dati dal database usando un datareader sql, anche se non viene restituito alcun valore if(rdr["Id"] != null)restituito truee alla fine ho lanciato un'eccezione per il cast di un valore nullo come numero intero.

Ma questo se uso i if (rdr["Id"] != System.DBNull.Value)ritorni false.

Qual è la differenza tra null e System.DBNull.Value?


Beh, non sono collegati. Uno è un'istanza statica di una classe in System.Datae l'altro è un valore speciale che indica la mancanza di un referente. Non hanno niente a che fare l'uno con l'altro. Puoi approfondire ciò su cui sei confuso? La tua vera domanda è "perché fare DataRowse DataReadersmettere DBNull.Valuedentro se stessi invece di null?"
mqp

Beh, inizialmente non lo era, ma dopo aver imparato da quello che hai detto, sono curioso. Puoi dirmi perché DataRows e DataReaders mettono DBNull.Value in se stessi invece di null?
pavanred

Non ne sono sicuro. Ecco una risposta: stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull/… È anche possibile che prima che i tipi di valore nullable fossero disponibili in C #, sarebbe stato più una seccatura da affrontare null.
mqp

1
Avevo una risposta qui, ma mi sono reso conto che era più adatto per stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull - quindi l'ho spostato
Marc Gravell

Risposte:


116

Ebbene, nullnon è un'istanza di alcun tipo. Piuttosto, è un riferimento non valido.

Tuttavia, System.DbNull.Valueè un riferimento valido a un'istanza di System.DbNull( System.DbNullè un singleton e System.DbNull.Valuefornisce un riferimento alla singola istanza di quella classe) che rappresenta valori inesistenti * nel database.

* Normalmente diremmo null, ma non voglio confondere la questione.

Quindi, c'è una grande differenza concettuale tra i due. La parola chiave nullrappresenta un riferimento non valido. La classe System.DbNullrappresenta un valore inesistente in un campo di database. In generale, dovremmo cercare di evitare di utilizzare la stessa cosa (in questo caso null) per rappresentare due concetti molto diversi (in questo caso un riferimento non valido rispetto a un valore inesistente in un campo di database).

Tieni presente che questo è il motivo per cui molte persone sostengono l'uso del modello di oggetti nulli in generale, che è esattamente ciò di cui System.DbNullè un esempio.


43
+1 Un esempio pratico: se si utilizza IDbCommand.ExecuteScalar(), può restituire null (nessun record restituito) o DbNull(la prima colonna nel primo record è un "valore inesistente"). Senza di DbNullte non saresti in grado di distinguere l'uno dall'altro.
C.Evenhuis

Consiglio vivamente di utilizzare un linguaggio che vieti l'uso di Null e lo fa a un costo aggiuntivo assolutamente pari a 0. la vita è troppo breve per "null object pattern"
nicolas

3
Un riferimento nullo è perfettamente valido. ☺
IllidanS4 vuole che Monica torni il

@ C.Evenhuis Bene, c'è un altro consiglio comune: una funzione dovrebbe restituire solo un tipo di valore. Questo è il motivo per cui le persone preferiscono un codice TypeScript ben digitato. "Qual è lo stato dell'esecuzione" è diverso da "Qual è il risultato computazionale". Cioè. avrebbero potuto decidere di implementare questa funzione in qualche altro modo (forse un parametro out o un oggetto simile agli oggetti di risposta alla richiesta HTTP). Certo, questa è una complicazione non voluta, ma se lo avessero fatto, forse sarebbe stato possibile utilizzare null al posto di DbNull.
klenium il

21

Dalla documentazione della classe DBNull :

Non confondere la nozione di null in un linguaggio di programmazione orientato agli oggetti con un oggetto DBNull. In un linguaggio di programmazione orientato agli oggetti, null indica l'assenza di un riferimento a un oggetto. DBNull rappresenta una colonna di database variante non inizializzata o inesistente.


11

DBNull.Value è fastidioso avere a che fare.

Uso metodi statici che controllano se è DBNull e quindi restituiscono il valore.

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

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

Inoltre, quando si inseriscono valori in un DataRow, non è possibile utilizzare "null", è necessario utilizzare DBNull.Value.

Avere due rappresentazioni di "null" è un cattivo design senza alcun vantaggio apparente.


2
Il sentimento di disgusto che condividiamo è: la tua ultima affermazione è superata solo dall'ironia di presentarti qui per leggere questo e scoprire che il tuo nome utente è "disgusto"
Iofacture

5

DBNull.Value è ciò che i provider di database .NET restituiscono per rappresentare una voce nulla nel database. DBNull.Value non è nullo e il confronto con nullo per i valori di colonna recuperati da una riga del database non funzionerà, dovresti sempre confrontare con DBNull.Value.

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


ps È inoltre necessario utilizzare DBNull.Value per passare un parametro null al database, altrimenti potrebbe essere interpretato poiché il parametro non è stato passato.
James Michael Hare

1
DBNull non è "ciò che restituisce il database", è semplicemente il modo in cui ADO.NET sceglie di interpretarlo; personalmente non sono sicuro che questa interpretazione sia molto valida
Marc Gravell

@MarcGravell Sì, Marc, hai ragione. L'ho formulato in modo errato. ASP.NET traduce il valore della colonna nulla del database in DBNull.Value
James Michael Hare

3

DataRow ha un metodo che viene chiamato IsNull()che puoi usare per testare la colonna se ha un valore nullo, rispetto al nullo come viene visto dal database.

DataRow["col"]==nullsarà sempre false.

uso

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

anziché.


3

Null è simile al puntatore zero in C ++ . Quindi è un riferimento che non punta a nessun valore .

DBNull.Valueè completamente diverso ed è una costante che viene restituita quando un valore di campo contiene NULL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.