2012-03-16 9 views
12

Tenemos un código que archiva datos de una base de datos de Microsoft Access en una base de datos de MS SQL Server. Suponiendo que tenemos un lector de datos ya poblado de la tabla de Access y estamos agregando un parámetro a un SqlCommand en preparación para la inserción, tenemos un tipo de transmisión que está fallando. Aquí está el código:¿Por qué falla este reparto de corto a int?

oSqlServerDbCmd_ForInsert.Parameters.AddWithValue("@Duration", 
    (int) oReader["Duration"]); 

El campo de la oReader en realidad es un número entero de acceso, que es un corto en C#. Si hacemos un corto aquí, no hay problema. Sin embargo, si lanzamos a un int el código arroja una InvalidCastException. Puedo estar malinterpretando esto desde MSDN documentation:

"Hay una conversión implícita predefinida de corto a int, largo, flotante, doble o decimal".

... pero parece que esto debería funcionar (siendo mi razonamiento, si se define una conversión implícita, ¿por qué no funcionaría un tipo de conversión explícito?). Me doy cuenta de que el elenco ni siquiera es necesario porque AddWithValue acepta un objeto, por lo que hemos eliminado el elenco de nuestro código, pero me gustaría ver una explicación de por qué falla este elenco en caso de que encontremos algo como esto en el futuro.

+1

Buen artículo de Eric Lippert en este http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx –

+0

esto no es una respuesta a su pregunta, pero parece que su parámetro '@ Duration' debe tener un tipo de datos numéricos, en cuyo caso no le gustaría usar un valor de cadena en la llamada 'AddWithValue'. – phoog

+0

@phoog Edité el código para eliminar esa conversión, ya que es una distracción de lo que realmente terminó siendo esta pregunta. La respuesta corta es que la conversión de cadena estaba en el código cuando la heredamos. Como funcionaba hasta que cambiamos el tipo de datos en el DB fuente, no teníamos motivos para investigar el código. Una vez que se rompió y cavamos, vimos que la conversión de cadenas era innecesaria (aunque no problemática, créanlo o no). –

Respuesta

18

Lo que tiene en sus manos es una instancia de unboxing. Específicamente, al desempaquetar, solo puede desempaquetar al tipo del valor originalmente encuadrado; si ese tipo es A y está desempacando en B, , no importa si existe una conversión implícita de A a B (el desempaquetado aún fallará).

Consulte el classic blog post de Eric Lippert sobre el tema para obtener una explicación detallada.

+0

+1 Siempre me olvido de eso. 'objeto o = (corto) 10; int i = (int) o; 'falla. –

+1

Ah, eso tiene sentido. Entonces, si fuera el primero en lanzarlo como un cortometraje, ¿podría lanzarlo como un int sin ningún problema? –

+1

@ awilson53: Exactamente. – Jon

5

Tienes que lanzar al tipo muy específico ya que se unboxing - el problema es que oReader["Duration"] devuelve un object ejemplo:

short myShort = 42; 
object o = myShort; 
int myInt = (int)o; //fails 

tendrá éxito si lanzas de nuevo a corto en primer lugar, a continuación, a int:

(int) (short) oReader["Duration"] 
+0

Gracias por los comentarios, +1 ... ambos respondieron mi pregunta, así que voy a tener que irme con la primera mudanza. –

Cuestiones relacionadas