2013-01-09 154 views
20

試圖找出是否最好使用ExecuteScalarExecuteNonQuery如果我想返回新插入行的標識列。我已閱讀this question,我理解這些差異存在,但找了一些代碼時,我寫了幾個星期前(同時從該網站大量舉債),我發現,在我插入我用ExecuteScalar,就像這樣:返回標識值時ExecuteScalar vs ExecuteNonQuery

public static int SaveTest(Test newTest) 
{ 
    var conn = DbConnect.Connection(); 
    const string sqlString = "INSERT INTO dbo.Tests (Tester , Premise) " + 
          "    VALUES (@tester , @premise) " + 
          "SET @newId = SCOPE_IDENTITY(); "; 
    using (conn) 
    { 
     using (var cmd = new SqlCommand(sqlString, conn)) 
     { 
      cmd.Parameters.AddWithValue("@tester", newTest.tester); 
      cmd.Parameters.AddWithValue("@premise", newTest.premise); 
      cmd.Parameters.Add("@newId", SqlDbType.Int).Direction = ParameterDirection.Output; 

      cmd.CommandType = CommandType.Text; 
      conn.Open(); 
      cmd.ExecuteScalar(); 

      return (int) cmd.Parameters["@newId"].Value; 
     } 
    } 
} 

能正常工作,我需要什麼,所以我不知道

  1. 我是否應該使用ExecuteNonQuery在這裏,因爲它是「更合適的」做插入?
  2. 由於我使用的是輸出參數,檢索標識值的方式是否相同?
  3. 是否有任何與單向或雙向相關的性能命中?
  4. 總體來說有更好的方法來做到這一點嗎?

我正在使用Visual Studio 2010,.NET 4.0和SQL Server 2008r2,以防有什麼區別。

+4

(1)爲什麼'ExecuteNonQuery'「更合適」? (2)您是否考慮過使用存儲過程?如果不是,爲什麼不呢?它肯定會幫助你清理所有你放入你的應用程序的臨時SQL - 當你必須改變它時,這意味着你必須重新編譯和重新部署應用程序。 –

+2

嗯...... ExecuteNonQuery通常用於執行不期望返回結果的SQL。 ExecuteScalar返回一個值,所以你不需要通過參數。你可以改變你的SQL的最後部分爲'SELECT SCOPE_IDENTITY();'然後使用'return(int)cmd.ExecuteScalar();' – Sam

+2

我使用'ExecuteScalar'因爲我使用'SELECT SCOPE_IDENTITY'沒有輸出參數,因此檢索「ExecuteScalar」的單個值。 http://stackoverflow.com/a/9319609/284240 –

回答

25

正如Aaron所建議的,存儲過程會讓它更快,因爲它可以節省Sql Server編譯SQL批處理的工作。但是,您仍然可以採取以下兩種方法:ExecuteScalarExecuteNonQuery。恕我直言,他們之間的表現差異是如此之小,以至於任何一種方法都是「適當的」。

話雖如此,如果您從輸出參數中獲取標識值,我沒有看到使用ExecuteScalar的要點。在這種情況下,由ExecuteScalar返回的值變得無用。

,我喜歡,因爲它需要較少的代碼的方法,使用ExecuteScalar無輸出參數:

public static int SaveTest(Test newTest) 
{ 
    var conn = DbConnect.Connection(); 
    const string sqlString = "INSERT INTO dbo.Tests (Tester , Premise) " + 
          "    VALUES (@tester , @premise) " + 
          "SELECT SCOPE_IDENTITY()"; 
    using (conn) 
    { 
     using (var cmd = new SqlCommand(sqlString, conn)) 
     { 
      cmd.Parameters.AddWithValue("@tester", newTest.tester); 
      cmd.Parameters.AddWithValue("@premise", newTest.premise); 

      cmd.CommandType = CommandType.Text; 
      conn.Open(); 
      return (int) (decimal) cmd.ExecuteScalar(); 

     } 
    } 
} 

快樂編程!

編輯:請注意,我們需要轉換兩次:從對象decimal,然後int(感謝techturtle的注意這一點)。

+0

我也遇到了投射問題。但有時候不需要,想知道爲什麼? – SamChen