2010-01-28 31 views
5

Bir kayıt eklemeye ve yeni oluşturulmuş kimliğini iki sorguyu tek tek yürüterek almaya çalışıyorum, ancak neden bana aşağıdaki hatayı verdiğini bilmiyorum.SCOPE_IDENTITY, asp.net'de çalışmıyor mu?

Object cannot be cast from DBNull to other types 

Kodum aşağıdaki gibidir:, kontrol ediniz da mümkünse

SqlParameter sqlParam; 
    int lastInsertedVideoId = 0; 

    using (SqlConnection Conn = new SqlConnection(ObjUtils._ConnString)) 
    { 
     Conn.Open(); 
     using (SqlCommand sqlCmd = Conn.CreateCommand()) 
     { 
      string sqlInsertValues = "@Name,@Slug"; 
      string sqlColumnNames = "[Name],[Slug]"; 
      string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + ");"; 
      sqlCmd.CommandText = sqlQuery; 
      sqlCmd.CommandType = CommandType.Text; 

      sqlParam = sqlCmd.Parameters.Add("@Name", SqlDbType.VarChar); 
      sqlParam.Value = txtName.Text.Trim(); 

      sqlParam = sqlCmd.Parameters.Add("@Slug", SqlDbType.VarChar); 
      sqlParam.Value = txtSlug.Text.Trim(); 


      sqlCmd.ExecuteNonQuery(); 

      //getting last inserted video id 
      sqlCmd.CommandText = "SELECT SCOPE_IDENTITY() AS [lastInsertedVideoId]"; 
      using (SqlDataReader sqlDr = sqlCmd.ExecuteReader()) 
      { 
       sqlDr.Read(); 
       lastInsertedVideoId = Convert.ToInt32(sqlDr["lastInsertedVideoId"]); 
      } 
     } 
    } 

    //tags insertion into tag table 
    if (txtTags.Text.Trim().Length > 0 && lastInsertedVideoId > 0) 
    { 
     string sqlBulkTagInsert = ""; 
     string[] tags = txtTags.Text.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); 
     foreach (string tag in tags) 
     { 
      sqlBulkTagInsert += "INSERT INTO tags(VideoId, Tag) VALUES(" + lastInsertedVideoId + ", " + tag.Trim().ToLowerInvariant()+ "); "; 
     } 

     using (SqlConnection Conn = new SqlConnection(ObjUtils._ConnString)) 
     { 
      Conn.Open(); 
      using (SqlCommand sqlCmd = Conn.CreateCommand()) 
      { 
       string sqlQuery = sqlBulkTagInsert; 
       sqlCmd.CommandText = sqlQuery; 
       sqlCmd.CommandType = CommandType.Text; 

       sqlCmd.ExecuteNonQuery(); 
      } 
     } 
    } 

Ve (ben sql saklı yordamları kullanmak istemiyorum) Yukarıdaki kod iyi kodlu ya da bunu optimize edebilirsiniz olduğunu performansı artırmak için daha fazla?

sayesinde

+0

SQL Server'da SCOPE_IDENTITY ve @@ IDENTITY: http://support.microsoft.com/default.aspx?scid=kb;en-US;2019779 –

cevap

9

SCOPE_IDENTITY() yöntemine yapılan çağrı, yürütmekte olduğunuz INSERT komutuyla aynı "kapsamda" kabul edilmiyor.

int lastVideoInsertedId = Convert.ToInt32(sqlCmd.ExecuteScalar()); 
yerine .ExecuteNonQuery ait

ve kod bloğunu çağrı ardından

string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + "); SELECT SCOPE_IDENTITY() AS [lastInsertedVideoId]"; 

ve:

string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + ");"; 

için:

Esasen, ne yapmak gerekir hattını değiştirmektir "// son eklenen video kimliği" yorumunu izleyerek.

+0

Güzel görünüyor, bunu deneyeyim. – Prashant

+0

Nedenini bilmiyorum ama onun bana verdiği 'System.InvalidCastException: Belirtilen cast geçerli değil. 'Hata yaptığım gibi int intVideoInsertedId = (int) sqlCmd.ExecuteScalar();' – Prashant

+0

Anladım: Denedim int lastVideoInsertedId = Convert.ToInt32 (sqlCmd.ExecuteScalar()); 've onun çalışması gibi. Sebebini bilmiyorum, lütfen açıklayınız. Ayrıca lütfen cevabınızı düzenleyin ve bu dönüşüm yöntemini ekleyin. Teşekkürler – Prashant

0

SCOPE_IDENTITY() birinci komuta (SELECT, RETURN veya OUT) elde edilir ve bir sonraki komut olarak kabul edilmelidir. Bununla, yani SELECT_IDENTITY(), ilk komutunun sonunda olmalıdır. SQL 2008'de, INSERT'un bir parçası olarak değerleri geri getirmek için ek sözdizimi vardır, bu da bunu kolaylaştırır.

Ya da daha verimli: gidiş-dönüşleri önlemek için komutları bir araya getirin.

+0

'da bulunan paralel yürütme hatalarını unutmayın. sqlCmd.ExecuteNonQuery(); 'bir değişkende kimlik değerini nasıl alacağız? ve bir kez daha sql saklı yordamları kullanmak istemiyorum. – Prashant

+0

Veya herhangi bir örnek kod sağlayabiliyor olsanız iyi olacak, teşekkürler. – Prashant

+0

Eğer bir "OUT" paramiyse, o zaman "ExecuteNonQuery" - bir "RETURN" parametresi ise ditto olur; eğer bir 'SELECT' ise,' ExecuteReader' veya 'ExecuteScalar' kullanın. 'OUT' /' RETURN''ün * marjinal olarak * SELECT'den daha verimli olduğunu, ancak çok fazla miktarda olmadığını unutmayın. –