web-dev-qa-db-ja.com

ExecuteScalar(); scope_identity()を使用して「System.InvalidCastException:指定されたキャストは無効です」を生成します

さまざまなデータを(テキストボックスとチェックボックスリストを介して)受け入れるフォームがあり、クリックイベントですべてのデータをテーブルに挿入し、scope_identityを選択して変数に格納し、チェックボックスリスト項目の挿入に使用します。別のテーブルへのループを使用する

多くの回答と例によると、これは完全に機能するはずです!..しかし、それは私にこのエラーを与えます:

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

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

これが私のリンクボタンメソッドコードです:

   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 Server Expressで直接実行すると、クエリは正常に機能します。

この奇妙な問題の奇妙な説明

Alexbによる最初の解決策:

私はそれをしました:)私のSQLサーバー2008は「オブジェクト」にパックされたSystem.Decimalを返します。キャストの代わりにSystem.Convert.ToInt32を使用してみてください。

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

私による2番目の解決策:

「SELECTscope_identity();」を使用する代わりに「SELECTBrandIdFROM Brands WHERE BrandId = @@ Identity;」を使用しましたそれはあなたにさらに多くの制御を与えますが、私は個人的に最初の解決策を前払いします

N.B: "SELECT @@ Identity;"また、うまく機能します

みんなありがとう、そして私はそれが他の人を助けることを願っています!

18
Mazen Elkashef

正確にcomm.ExecuteScalar()は何を返しますか?多分それはlongまたはdoubleに詰め込まれたobjectを返します。
正確には思い出せませんが、1〜2年前に何かに直面したようです。

7
alex.b

SQLを変更できる場合、さらに簡単な方法は次のようになります。

SELECT CONVERT(int, SCOPE_IDENTITY())
34
Maccer

Dimiが言ったように、IdentityはSQL数値(.NET Decimal)です。これは機能するはずです:

decimal decimalBrandId = (decimal)comm.ExecuteScalar(); 
int NewBrandId = (int)decimalBrandId;
4
BrianH

SCOPE_IDENTITY()のドキュメントから

Return Types

numeric(38,0) 

したがって、簡単な解決策は次のようになります

DECLARE @ReturnValue INT;

/*
   Do your insert stuff here.
*/

SELECT @ReturnValue = SCOPE_IDENTITY();
SELECT @ReturnValue;
2
Dimi Takis