2010-12-10 2 views
17

У меня есть форма, которая принимает различные данные (через текстовые поля и флажок), а при событии клика они вставляют все данные в таблицу и выбирают scope_identity затем сохранить его в переменной, чтобы использовать его в вставки CheckBoxList элементов, используя петлю в другую таблицуExecuteScalar(); С scope_identity() Генерация «System.InvalidCastException: указанное приведение недействительно»

по мнению многих ответов и примеров это должно работать отлично .. но это дает мне эту ошибку:

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

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

Вот мой LinkButton код метода:

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(); 
      } 
     } 
    } 

Редактировать Странно, что запрос работает нормально, когда я запускаю его непосредственно в sql-сервере express visual studio!

Странная Объяснение этому Weird Проблема

Первое решение по AlexB:

Я сделал это :) Мой SQL Server 2008 возвращает System.Decimal упакованы в 'объект'. Попробуйте использовать System.Convert.ToInt32 вместо отливки.

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

Второе решение мной:

вместо того, чтобы использовать "SELECT SCOPE_IDENTITY();" Я использовал «SELECT BrandId FROM Brands WHERE BrandId = @@ Identity;" это дает вам еще больше controlm, но я лично заранее предварял

N.B: "SELECT @@ Identity;" будет также работы просто отлично

Спасибо, ребята, и я надеюсь, что это поможет другим!

+1

Существует несколько причин, по которым вы должны использовать SCOPE_IDENTITY() вместо @@ IDENTITY. Попробуйте вместо этого применить SCOPE_IDENTITY() к INT внутри вашей процедуры. – Rory

ответ

6

Что именно comm.ExecuteScalar() возвращается? Возможно, он возвращает long или double упакован в object.
точно не помню, но, похоже, я столкнулся с чем-то 1-2 года назад.

+0

на самом деле он возвращает int, который, я думаю, является правильной используемой литой в "(int) comm.ExecuteScalar();" и я также проверил этот запрос непосредственно на сервере sql, и он сработал! – lKashef

+4

SCOPE_IDENTITY() возвращает десятичное значение (38,0), которое .net не позволит вам преобразовать в int. Ниже приведенное ниже предложение @ Maccer для легкого изменения proc, в противном случае выполните преобразование decimal => int в .net. – Rory

+0

@Rory вы должны вставить это как ответ, потому что это (ваш) правильный ответ. –

-1

попробуйте добавить SET NOCOUNT ON; перед вставкой.

+0

по-прежнему такая же ошибка! : S Я думаю, что разрешение alexb прав, но я уверен, что мой тип данных Id - INT, и я думаю, что я предоставил правильный листинг, и я уже видел код уже из этого вопроса >> http://stackoverflow.com/questions/1126171/select-the-last-row-in-a-sql-table Интересно ...! =) – lKashef

+0

, а затем напечатайте имя типа возвращаемого значения для вывода отладки и посмотрите, что это такое. –

+2

Я сделал это :) Мой SQL Server 2008 возвращает 'System.Decimal', упакованный в 'object'. Попробуйте использовать 'System.Convert.ToInt32' вместо броска. –

2

Из документации scope_identity()

Return Types 

numeric(38,0) 

Так простое решение будет следующим

DECLARE @ReturnValue INT; 

/* 
    Do your insert stuff here. 
*/ 

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

Если вы можете изменить SQL, даже проще всего было бы

SELECT CONVERT(int, SCOPE_IDENTITY()) 
+1

Проблема старая, но +1 для другого простого возможного решения – lKashef

4

Как сказал Дими, Identity является SQL-номером (.NET Decimal).Это должно работать:

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

или 'var newBrandID = (int) (десятичный) comm.ExecuteScalar();' – Todd

Смежные вопросы