2011-02-10 10 views
71

¿Hay alguna diferencia entre null y System.DBNull.Value? ¿Y si si, que?¿Cuál es la diferencia entre null y System.DBNull.Value?

me di cuenta de este comportamiento ahora -

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

Mientras recuperar datos de la base de datos utilizando un datareader SQL, aunque no hay valor devuelto if(rdr["Id"] != null) regresado true y, finalmente, lanzó una excepción para la fundición de un nulo como entero.

Pero, esto si uso if (rdr["Id"] != System.DBNull.Value) devuelve false.

¿Cuál es la diferencia entre null y System.DBNull.Value?

+0

Bueno, no tienen relación. Una es una instancia estática de una clase en 'System.Data', y la otra es un valor especial que significa la falta de un referente. No tienen nada que ver el uno con el otro. ¿Puedes explicar en qué estás confundido? ¿Es su verdadera pregunta "por qué' DataRows' y 'DataReaders' ponen' DBNull.Value' dentro de sí mismos en lugar de 'null'?" – mquander

+0

Bueno, mi no fue inicialmente pero después de aprender de lo que dijiste, tengo curiosidad. ¿Podría decirme por qué DataRows y DataReaders ponen DBNull.Value en sí mismos en lugar de nulo? – pavanred

+0

No estoy seguro de mí mismo. Aquí hay una respuesta: http://stackoverflow.com/questions/4488727/what-is-the-point-of-dbnull/4488758#4488758 También es posible que antes de que los tipos de valores anulables estuvieran en C#, habría sido más de una molestia para lidiar con 'null'. – mquander

Respuesta

89

Bueno, null no es una instancia de cualquier tipo. Más bien, es una referencia inválida.

Sin embargo, System.DbNull.Value, es una referencia válida a una instancia de System.DbNull (System.DbNull es un producto único y System.DbNull.Value le da una referencia a la única instancia de esa clase) que representa inexistentes * valores en la base de datos.

* Normalmente decimos null, pero no quiero confundir el problema.

Por lo tanto, hay una gran diferencia conceptual entre los dos. La palabra clave null representa una referencia no válida. La clase System.DbNull representa un valor inexistente en un campo de base de datos. En general, deberíamos intentar evitar usar lo mismo (en este caso null) para representar dos conceptos muy diferentes (en este caso, una referencia no válida frente a un valor inexistente en un campo de base de datos).

Tenga en cuenta que esta es la razón por la que mucha gente abogue por el uso de null object pattern en general, que es exactamente lo que System.DbNull es un ejemplo de.

+31

+1 Un ejemplo práctico: si usa 'IDbCommand.ExecuteScalar()', puede devolver nulo (no se devuelve ningún registro) o 'DbNull' (primera columna en primer el registro es un 'valor inexistente'). Sin 'DbNull' no sería capaz de distinguir uno de otro. –

+0

Recomiendo encarecidamente utilizar un lenguaje que prohíba el uso de nulo, y lo hace a un costo absolutamente cero. la vida es demasiado corta para el "patrón de objeto nulo" – nicolas

+2

Una referencia nula es perfectamente válida. ☺ – IllidanS4

5

DBNull.Value es lo que los proveedores de la base de datos .NET devuelven para representar una entrada nula en la base de datos. DBNull.Value no es nulo y las comparaciones con null para los valores de columna recuperados de una fila de base de datos no funcionarán, siempre se debe comparar con DBNull.Value.

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

+0

p.s. También debe usar DBNull.Value para pasar un parámetro nulo a la base de datos, de lo contrario, puede interpretarse ya que el parámetro no se pasó. –

+0

DBNull es * no * "lo que devuelve la base de datos" - es simplemente cómo ADO.NET decide interpretarlo; personalmente no estoy seguro de que esta interpretación sea muy valiosa –

+0

@MarcGravell Sí, Marc, tienes razón. Lo formulé incorrectamente. ASP.NET traduce el valor de columna nulo de la base de datos en DBNull.Value –

3

DataRow tiene un método que se llama IsNull() que puede usar para probar la columna si tiene un valor nulo, con respecto al nulo tal como lo ve la base de datos.

DataRow["col"]==null siempre será false.

uso

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

lugar.

2

Nulo es similar a puntero cero en C++. Por lo tanto, es una referencia que no apunta a ningún valor.

DBNull.Value es completamente diferente y es constante que se devuelve cuando un valor de campo contiene NULL.

20

De la documentación de la DBNull class:

No hay que confundir la noción de null en un lenguaje de programación orientado a objetos con un objeto DBNull. En un lenguaje de programación orientado a objetos, null significa la ausencia de una referencia a un objeto. DBNull representa una variante no inicializada o una columna de base de datos inexistente.

8

DBNull.Value es molesto de tener que tratar.

Utilizo métodos estáticos que comprueban si es DBNull y luego devuelven el valor.

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

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

Además, al insertar valores en un DataRow, no se puede utilizar "nulo", usted tiene que utilizar DBNull.Value.

Tener dos representaciones de "nulo" es un mal diseño sin ningún beneficio aparente.

Cuestiones relacionadas