ExecuteScalar vs ExecuteNonQuery when returning an identity value

。_饼干妹妹 提交于 2019-11-26 11:02:10

问题


Trying to figure out if it\'s best to use ExecuteScalar or ExecuteNonQuery if I want to return the identity column of a newly inserted row. I have read this question and I understand the differences there, but when looking over some code I wrote a few weeks ago (whilst heavily borrowing from this site) I found that in my inserts I was using ExecuteScalar, like so:

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;
        }
    }
}

This works fine for what I need, so I\'m wondering

  1. Whether I should be using ExecuteNonQuery here because it is \"more proper\" for doing inserts?
  2. Would retrieving the identity value be the same either way since I\'m using an output parameter?
  3. Are there any performance hits associated with one way or the other?
  4. Is there generally a better way to do this overall?

I\'m using Visual Studio 2010, .NET 4.0, and SQL Server 2008r2, in case that makes any difference.


回答1:


As suggested by Aaron, a stored procedure would make it faster because it saves Sql Server the work of compiling your SQL batch. However, you could still go with either approach: ExecuteScalar or ExecuteNonQuery. IMHO, the performance difference between them is so small, that either method is just as "proper".

Having said that, I don't see the point of using ExecuteScalar if you are grabbing the identity value from an output parameter. In that case, the value returned by ExecuteScalar becomes useless.

An approach that I like because it requires less code, uses ExecuteScalar without output parameters:

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();

        }
    }
}

Happy programming!

EDIT: Note that we need to cast twice: from object to decimal, and then to int (thanks to techturtle for noting this).



来源:https://stackoverflow.com/questions/14246744/executescalar-vs-executenonquery-when-returning-an-identity-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!