C# 返回标识值时ExecuteScalar vs ExecuteOnQuery
试图确定如果要返回新插入行的标识列,最好使用C# 返回标识值时ExecuteScalar vs ExecuteOnQuery,c#,sql-server,executenonquery,executescalar,C#,Sql Server,Executenonquery,Executescalar,试图确定如果要返回新插入行的标识列,最好使用ExecuteScalar或ExecuteNonQuery。我已经阅读并理解了其中的差异,但当查看几周前我编写的一些代码(同时大量借用了本网站的内容)时,我发现在我的插入中我使用的是ExecuteScalar,如下所示: publicstaticintsavetest(testnewtest) { var conn=DbConnect.Connection(); const string sqlString=“插入dbo.Tests(测试人员,前提)”
ExecuteScalar
或ExecuteNonQuery
。我已经阅读并理解了其中的差异,但当查看几周前我编写的一些代码(同时大量借用了本网站的内容)时,我发现在我的插入中我使用的是ExecuteScalar
,如下所示:
publicstaticintsavetest(testnewtest)
{
var conn=DbConnect.Connection();
const string sqlString=“插入dbo.Tests(测试人员,前提)”+
“值(@tester,@premise)”+
“SET@newId=SCOPE_IDENTITY();”;
使用(康涅狄格州)
{
使用(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();
返回(int)cmd.Parameters[“@newId”].Value;
}
}
}
这对我需要的很好,所以我想知道
ExecuteNonQuery
,因为它“更适合”进行插入李>
我使用的是Visual Studio 2010、.NET 4.0和SQL Server 2008r2,以防万一会有什么不同。正如Aaron所建议的,存储过程会使它更快,因为它可以节省SQL Server编译SQL批处理的工作。但是,您仍然可以使用这两种方法:
ExecuteScalar
或ExecuteNonQuery
。嗯,它们之间的性能差异是如此之小,以至于任何一种方法都是“合适的”
话虽如此,如果要从输出参数获取标识值,我不认为使用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();
}
}
}
快乐编程
编辑:请注意,我们需要强制转换两次:从object到
decimal
,然后到int
(感谢TechTurl注意到这一点) (1)为什么ExecuteNonQuery
更合适?(2) 您是否考虑过使用存储过程?若否,原因为何?这肯定会有助于清理你放入应用程序中的所有临时SQL—当你必须更改它时,这意味着你必须重新编译并重新部署应用程序。嗯。。。ExecuteOnQuery通常用于执行不希望返回结果的SQL。ExecuteScalar返回一个值,因此不需要传递参数。您可以将SQL的最后一部分更改为SELECT SCOPE_IDENTITY()
然后使用返回(int)cmd.ExecuteScalar()
我使用ExecuteScalar
,因为我使用SELECT SCOPE\u IDENTITY
而没有输出参数,因此检索单个值,这是ExecuteScalar
的目的。需要记住的一件重要事情是应用程序的结构、目标和最简单的方法。正如Aaron所说,您可以走存储过程路线;您甚至可以利用大型查询来提取数据并在代码中编译它们。这是一个偏好的问题。但山姆在“通用”方面是正确的。@TimSchmelter就是这样做的。我永远不会猜到整个数值
的事情,尤其是因为我的标识列是int
(并且它在输出参数上不进行强制转换)。我甚至找到了那个,我也遇到了铸造问题。但有时它是不需要的,不知道为什么?我也使用这种方法(ExecuteScalar,在SQL命令后附加SCOPE_标识。唯一的“问题”是,如果您使用通用插入函数的这种方法,并将一个表传递给它(gasp)没有标识驱动的主键。如果是这样,您将得到一个错误在VB.NET中从类型“DBNull”转换为类型“String”是无效的(询问我如何知道),我假设您也会得到该错误的c#等价物。