问题描述
试图找出是否最好使用的ExecuteScalar
或的ExecuteNonQuery
如果我想返回的标识列新插入的行。我已阅读并我理解的差异存在,但找了一些代码,当我写了几个星期前(同时从本网站大量举债),我发现,在我插入我使用的ExecuteScalar
,像这样:
公共静态INT SaveTest(测试newTest)
{
变种康恩= DbConnect.Connection();
常量字符串的SqlString =INSERT INTO dbo.Tests(测试仪,前提)+
VALUES(@tester,@premise)+
SET @newId = SCOPE_IDENTITY(); ;
使用(康涅狄格州)
{
使用(VAR CMD =新的SqlCommand(的SqlString,康涅狄格州))
{
cmd.Parameters.AddWithValue(@测试仪, newTest.tester);
cmd.Parameters.AddWithValue(@前提,newTest.premise);
cmd.Parameters.Add(@ NEWID,SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.CommandType = CommandType.Text;
conn.Open();
cmd.ExecuteScalar();
回报(INT)cmd.Parameters [@ NEWID]值。
}
}
}
这正常工作对我需要的,所以我不知道
- 我是否应该使用
的ExecuteNonQuery
这里,因为它是更恰当做插入? - 会检索标识值是相同无论哪种方式,因为我使用的是输出参数?
- 是否有一个方式或其他相关的任何性能命中?
- 有一般
我使用Visual更好的方式来做到这一点的整体?
Studio 2010中,.NET 4.0和SQL Server 2008R2,万一有什么差别。
正如亚伦建议因为它节省了Sql Server的编译SQL批处理的工作存储过程将使它更快。但是,你仍然可以去用两种方法:的ExecuteScalar
或的ExecuteNonQuery
。 IMHO,它们之间的性能差异是如此之小,即任一方法只为合适。
话虽如此,我没有看到使用的点的ExecuteScalar
如果你抓住从标识值输出参数。在这种情况下,由的ExecuteScalar
返回的值变得无用。
这是我喜欢的,因为它需要较少的代码,使用一个方法的ExecuteScalar
无输出参数:
公共静态INT SaveTest(测试newTest)
{
VAR康恩= DbConnect.Connection();
常量字符串的SqlString =INSERT INTO dbo.Tests(测试仪,前提)+
VALUES(@tester,@premise)+
SELECT SCOPE_IDENTITY();
使用(康涅狄格州)
{
使用(VAR CMD =新的SqlCommand(的SqlString,康涅狄格州))
{
cmd.Parameters.AddWithValue(@测试仪, newTest.tester);
cmd.Parameters.AddWithValue(@前提,newTest.premise);
cmd.CommandType = CommandType.Text;
conn.Open();
回报(INT)(十进制)cmd.ExecuteScalar();
}
}
}
快乐编程!
修改:请注意,我们需要转换两次:从对象到小数
,然后到 INT
(感谢techturtle的注意这一点)。
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
- Whether I should be using
ExecuteNonQuery
here because it is "more proper" for doing inserts? - Would retrieving the identity value be the same either way since I'm using an output parameter?
- Are there any performance hits associated with one way or the other?
- 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.
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).
这篇关于的ExecuteScalar VS的ExecuteNonQuery返回一个标识值时,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!