2013-01-09 250 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