2010-12-10 13 views
17

Tengo un formulario que acepta varios datos (a través de cuadros de texto y una casilla de verificación) y en el evento click inserta todos los datos en una tabla y selecciona la SCOPE_IDENTITY luego almacenarla en una variable para utilizarlo en la inserción de los elementos CheckBoxList utilizando un bucle en otra tablaExecuteScalar(); Con scope_identity() Generando "System.InvalidCastException: Cast especificado no es válido"

acuerdo con muchas respuestas y ejemplos de esto debería funcionar perfectamente .. pero me da este error:

Exception Details: System.InvalidCastException: Specified cast is not valid. 

Line 66:    int NewBrandId = (int)comm.ExecuteScalar(); 

Aquí es mi LinkButton código de método:

protected void lnkbtnUploadAndSubmit_Click(object sender, EventArgs e) 
    { 
     SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MOODbCenterConnection"].ConnectionString); 

     SqlCommand comm = new SqlCommand("INSERT INTO Brands (BrandName, BrandLogo, BrandWebsite, IsBrandVisible) VALUES (@Name, @Logo, @Website, @IsVisible); SELECT scope_identity();", conn); 

     comm.Parameters.Add("@Name", System.Data.SqlDbType.NVarChar, 50); 
     comm.Parameters["@Name"].Value = txtbxBrandName.Text; 

     comm.Parameters.Add("@Logo", System.Data.SqlDbType.Text); 
     comm.Parameters["@Logo"].Value = fileuploadLogo.PostedFile.FileName; 

     comm.Parameters.Add("@Website", System.Data.SqlDbType.Text); 
     comm.Parameters["@Website"].Value = txtbxWebsite.Text; 

     comm.Parameters.Add("@IsVisible", System.Data.SqlDbType.Bit); 
     comm.Parameters["@IsVisible"].Value = chkbxIsPublished.Checked; 
     conn.Open(); 


     int NewBrandId = (int)comm.ExecuteScalar(); 

     conn.Close(); 

     foreach (ListItem li in chkbxlstCuisines.Items) 
     { 
      if (li.Selected) 
      { 
       conn.Open(); 

       SqlCommand comm2 = new SqlCommand("INSERT INTO BrandCuisines (CuisineId, BrandId) VALUES (@CuisineId, @NewBrandId)", conn); 

       comm2.Parameters.Add("@CuisineId", System.Data.SqlDbType.Int); 
       comm2.Parameters["@CuisineId"].Value = li.Value; 

       comm2.Parameters.Add("@NewBrandId", System.Data.SqlDbType.Int); 
       comm2.Parameters["@NewBrandId"].Value = NewBrandId; 
       comm2.ExecuteNonQuery(); 
       conn.Close(); 
      } 
     } 
    } 

Edit Extrañamente, la consulta funciona bien cuando la ejecuto directamente en el servidor sql express del visual studio.

la explicación extraño para este Problema extraño

primera solución por AlexB:

lo hice :) Mi servidor SQL 2008 vuelve System.Decimal empaquetados en 'objeto'. Intente utilizar System.Convert.ToInt32 en lugar de emitir.

Example : int NewBrandId = System.Convert.ToInt32(comm.ExecuteScalar()); 

Segunda solución por mí:

en lugar de utilizar "SELECT SCOPE_IDENTITY();" Utilicé "SELECT BrandId FROM Marcas WHERE BrandId = @@ Identity;" te da incluso más control , pero yo personalmente prefare la primera solución

N.B: "SELECCIONE @@ Identidad;" también funcionaría

Gracias chicos y espero que ayude a los demás!

+1

Existen varios motivos por los que debe usar SCOPE_IDENTITY() en lugar de @@ IDENTITY. Intenta convertir SCOPE_IDENTITY() en INT en tu procedimiento. – Rory

Respuesta

6

¿Qué devuelve exactamente comm.ExecuteScalar()? Quizás devuelve long o double embalado en object.
no recuerdo exactamente, pero parece que me enfrenté a algo hace 1-2 años.

+0

en realidad devuelve int que creo que es el molde usado correcto en "(int) comm.ExecuteScalar();" ¡y también probé esta consulta directamente en el servidor sql y funcionó! – lKashef

+4

SCOPE_IDENTITY() devuelve decimal (38,0), que .net no le permitirá convertir a un int. Consulte la sugerencia de @ Maccer a continuación para un cambio sencillo en el proceso, de lo contrario, realice la conversión decimal => int en .net. – Rory

+0

@Rory debe pegar esto como respuesta porque esta es (suya) la respuesta correcta. –

-1

intente agregar SET NOCOUNT ON; antes del inserto.

+0

sigue siendo el mismo error! : S Creo que la resolución de alexb es correcta, pero estoy seguro de que mi tipo de datos Id es INT y creo que proporcioné el modelo correcto, además ya vi el código de esta pregunta >> http://stackoverflow.com/questions/1126171/select-the-last-row-in-a-sql-table ¡Me pregunto ...! =) – lKashef

+0

, entonces imprima el nombre del tipo del valor devuelto a la salida de depuración y vea qué es. –

+2

Lo hice :) Mi servidor sql 2008 devuelve 'System.Decimal' empaquetado en 'objeto'. Intenta usar 'System.Convert.ToInt32' en lugar de lanzar. –

2

De la documentación para SCOPE_IDENTITY()

Return Types 

numeric(38,0) 

Así que una solución fácil sería la siguiente

DECLARE @ReturnValue INT; 

/* 
    Do your insert stuff here. 
*/ 

SELECT @ReturnValue = SCOPE_IDENTITY(); 
SELECT @ReturnValue; 
31

Si puede cambiar el SQL, una forma aún más fácil sería

SELECT CONVERT(int, SCOPE_IDENTITY()) 
+1

El problema es antiguo, pero +1 para otra solución posible simple – lKashef

4

Como dijo Dimi, Identity es un SQL numérico (.NET Decimal).Esto debería funcionar:

decimal decimalBrandId = (decimal)comm.ExecuteScalar(); 
int NewBrandId = (int)decimalBrandId; 
+0

o 'var newBrandID = (int) (decimal) comm.ExecuteScalar();' – Todd

Cuestiones relacionadas