ExecuteScalar (); С scope_identity () Генерация "System.InvalidCastException: Указанный приведение недействителен" [дубликат]

17

У меня есть форма, которая принимает различные данные (через текстовые поля и контрольный список), а при событии клика они вставляют все данные в таблицу и выбирают scope_identity, а затем сохраняют ее в переменной, чтобы использовать ее при вставке элементы checkboxlist, используя цикл в другую таблицу

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

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!

Странное объяснение этой странной проблемы

Первое решение от alexb:

  

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

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

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

  

вместо "SELECT   scope_identity (); «Я использовал« SELECT »   BrandId ОТ Брендов WHERE BrandId =   @@ Identity; "это дает вам еще больше   но я лично   первое решение

     

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

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

    
задан lKashef 10.12.2010 в 21:49
источник
  • Существуют различные причины, по которым вы должны использовать SCOPE_IDENTITY () вместо @@ IDENTITY. Попробуйте вместо этого применить SCOPE_IDENTITY () к INT внутри вашей процедуры. –  Rory 21.08.2012 в 11:39

5 ответов

6

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

ответ дан alex.b 10.12.2010 в 21:54
  • на самом деле он возвращает int, который, по моему мнению, является правильным использованием в "(int) comm.ExecuteScalar ();" и я также проверил этот запрос непосредственно на сервере sql, и он сработал! –  lKashef 10.12.2010 в 21:57
  • SCOPE_IDENTITY () возвращает десятичный (38,0), который .net не позволит вам преобразовать в int. Ниже приведенное ниже предложение @ Maccer для легкого изменения proc, в противном случае выполните преобразование decimal => int в .net. –  Rory 21.08.2012 в 11:38
  • @Rory вы должны вставить это как ответ, потому что это (ваш) правильный ответ. –  Royi Namir 19.06.2013 в 14:13
31

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

SELECT CONVERT(int, SCOPE_IDENTITY())
    
ответ дан Maccer 03.04.2011 в 22:25
  • Проблема старая, но +1 для другого простого возможного решения –  lKashef 03.04.2011 в 22:46
4

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

decimal decimalBrandId = (decimal)comm.ExecuteScalar(); 
int NewBrandId = (int)decimalBrandId;
    
ответ дан BrianH 30.10.2013 в 15:15
  • или var newBrandID = (int) (десятичный) comm.ExecuteScalar (); –  Todd 23.08.2015 в 12:31
2

Из документации для SCOPE_IDENTITY ()

Return Types

numeric(38,0) 

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

DECLARE @ReturnValue INT;

/*
   Do your insert stuff here.
*/

SELECT @ReturnValue = SCOPE_IDENTITY();
SELECT @ReturnValue;
    
ответ дан Dimi Toulakis 09.02.2011 в 12:54
-1

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

    
ответ дан Ilia G 10.12.2010 в 22:10
  • все та же ошибка! : SI думаю, что разрешение alexb прав, но я уверен, что мой тип данных Id - INT, и я думаю, что я предоставил правильный листинг, и я уже видел код уже из этого вопроса >> stackoverflow.com/questions/1126171/... Интересно .. .! знак равно –  lKashef 10.12.2010 в 22:13
  • , чтобы затем напечатать имя типа возвращаемого значения для вывода отладки и посмотреть, что это такое. –  Ilia G 10.12.2010 в 22:20
  • Я сделал это :) Мой SQL Server 2008 возвращает System.Decimal, упакованную в «объект». Попробуйте использовать System.Convert.ToInt32 вместо броска. –  alex.b 10.12.2010 в 22:27
  • ничего себе довольно странно –  Ilia G 10.12.2010 в 22:29
  • wow alexb, я просто сдался и попытался найти альтернативные решения =) .. это странно и по-настоящему: S: D –  lKashef 10.12.2010 в 22:34