2011-12-06 8 views
8

Estoy analizando XML (LINQ a XML) y estoy usando un tipo de nulo (int? y decimal?) en los casos en que el elemento/atributo está vacío. Sin embargo, cuando construyo mi colección para pasarla al DB (usando TVP) no sé cómo manejar los casos donde el valor es realmente nulo. No puedo pasar un nulo en SqlDataRecord SetInt32 o SetDecimal y no quiero establecerlo en cero ... De hecho, quiero que sea nulo.¿Cómo maneja el tipo anulable con SqlDataRecord

Diciéndome que no hay sobrecarga para int?

Conde a continuación es un tipo anulable (int? Conde)

SqlDataRecord rec = new SqlDataRecord(
       new SqlMetaData("Name", SqlDbType.VarChar, 50), 
       new SqlMetaData("Type", SqlDbType.VarChar, 50), 
       new SqlMetaData("Count", SqlDbType.Int)); 

    rec.SetString(0, dm.Name); 
    rec.SetString(1, dm.Type); 
    rec.SetString(2, dm.Count); 

Alguna idea de cómo manejar esto sin pasar a cero (manteniendo la hipótesis nula)?

Respuesta

10

método de extensión:

static class SqlDataRecordExtensions 
{ 
    static void SetNullableInt32(this SqlDataRecord rec, int index, Int32? value) 
    { 
     if (value.HasValue) 
      rec.SetInt32(index, value.GetValueOrDefault()); 
     else 
      rec.SetDBNull(index); 
    } 
} 

o, para usar SetSqlInt32 como sugiere D Stanley:

static class SqlDataRecordExtensions 
{ 
    static void SetNullableInt32(this SqlDataRecord rec, int index, Int32? value) 
    { 
     rec.SetSqlInt32(index, value.HasValue ? value.GetValueOrDefault() : SqlInt32.Null); 
     //          ^^^^^^^^^^^^^^^^^^^^^^^^^ 
     //          You can leave out the cast to (SqlInt32), 
     //          because the conversion is implicit 
    } 
} 

Nota 9 Dic 2013: Volviendo a esta respuesta debido a un comentario , Noté una pequeña oportunidad de mejora, basada en la serie de Eric Lippert sobre micro optimizaciones para nulos, que se puede encontrar en http://ericlippert.com/2012/12/20/nullable-micro-optimizations-part-one/.

En resumen, mientras que la propiedad Value requiere menos tipeo y, por tanto, podría decirse que es más óptima para el programador, tiene que lanzar una excepción si HasValue es falso. Por otro lado, el método GetValueOrDefault() es un acceso de campo simple. Debido a esto, GetValueOrDefault() requiere menos instrucciones y es más probable que esté en línea, por lo que es más óptimo para el compilador y el procesador.

+0

+1, muy agradable ... –

+0

SetValue (ordinal, object) maneja nulables y valores nulos con un poco de sobrecarga para tipo y verificación de la longitud del valor. La diferencia de rendimiento puede no ser notable. –

+0

@RichardCollette Gracias por el comentario; No pensé en eso. Sospecho que tienes razón en que la diferencia de rendimiento probablemente sea insignificante para la mayoría de las aplicaciones. Tiendo a preferir una tipificación más fuerte por motivos filosóficos, sin embargo. Tu comentario también me inspira a agregar una pequeña optimización en la que no pensé hace dos años. – phoog

3

Nunca había trabajado con SqlDataRecord, pero cuando se utiliza DataTable y DataRow, o cuando se utilizan consultas con parámetros, que especifico null usando DBNull.Value.

Con SqlDataRecord, parece que puede usar el método SetDBNull.

0

Debe usar SetSqlInt32 en lugar de SetString. Trate

rec.SetSqlInt32(2, (dm.Count.HasValue ? new SqlInt32(dm.Count) : SqlInt32.Null)); 
+0

que tendría que ser la comprobación 'rec.SetSqlInt32 (2, (dm.Count.HasValue? new SqlInt32 (dm.Count.Value): SqlInt32.Null));' – phoog

+0

Además, como me di cuenta al editar mi respuesta, la conversión implícita de int a SqlInt32 significa usted puede hacer esto: 'rec.SetSqlInt32 (2, dm.Count.HasValue? dm.Count.Value: SqlInt32.Null);' – phoog

0

// He encontrado que esto funcione lo mejor para mí en la comprobación o tratar con tipos anulables // en mi ejemplo estoy valores almacenados en un String [] array

sqlcmdUpdateRecord.Parameters.AddWithValue("@strSomeValue", (strRecord[(int) 
DataFields.SomeDataField] as object) ?? DBNull.Value); 
Cuestiones relacionadas