Esta pregunta aparece ocasionalmente, pero no he visto una respuesta satisfactoria.¿La forma más eficiente de verificar DBNull y luego asignarla a una variable?
Un patrón típico es (fila es un DataRow ):
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
Mi primera pregunta es que es más eficiente (he volteado la condición):
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
This indica ese .GetType() debería ser más rápido, pero tal vez el compilador sepa algunos trucos que yo no?
Segunda pregunta, ¿vale la pena almacenar en caché el valor de la fila ["value"] o el compilador optimiza el indexador de todos modos?
Por ejemplo:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Notas:
- fila [ "valor"] existe.
- No conozco el índice de la columna (de ahí la búsqueda del nombre de la columna).
- Pregunto específicamente sobre la comprobación de DBNull y su asignación (no sobre la optimización prematura, etc.).
I Benchmarked algunos escenarios (tiempo en segundos, 10,000,000 de ensayos):
row["value"] == DBNull.Value: 00:00:01.5478995
row["value"] is DBNull: 00:00:01.6306578
row["value"].GetType() == typeof(DBNull): 00:00:02.0138757
Object.ReferenceEquals tiene el mismo rendimiento que "=="
El resultado más interesante? Si falta de coincidencia del nombre de la columna por caso (por ejemplo, "Valor" en lugar de "valor", se tarda aproximadamente diez veces más (para una cadena):
row["Value"] == DBNull.Value: 00:00:12.2792374
La moraleja de la historia parece haber que si no se puede mirar hacia arriba una columna por su índice, y luego asegurarse de que el nombre de la columna que alimenta al controlador paso a paso coincide con el nombre de la DataColumn exactamente
el almacenamiento en caché el valor también parece ser casi dos veces tan rápido:.
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Así que la mayoría método eficiente parece ser:
object temp;
string variable;
if (DBNull.Value != (temp = row["value"]))
{
variable = temp.ToString();
}
Puede aclarar si la fila es un DataRow o un IDataRecord/IDataReader? –
Es un DataRow, lo siento. – ilitirit
Ahora tenemos mucho mejor .NET Framework y podemos usar [DataRowExtensions Methods] (http://msdn.microsoft.com/en-us/library/bb359893.aspx). –