Essayer de déterminer s'il est préférable d'utiliser ExecuteScalar
ou ExecuteNonQuery
si je veux renvoyer la colonne d'identité d'une ligne nouvellement insérée. J'ai lu cette question et je comprends les différences, mais en examinant du code que j'ai écrit il y a quelques semaines (tout en empruntant beaucoup à ce site), j'ai trouvé que dans mes encarts j'utilisais ExecuteScalar
, comme ceci:
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;
}
}
}
Cela fonctionne bien pour ce dont j'ai besoin, donc je me demande
ExecuteNonQuery
ici parce que c'est "plus approprié" pour faire des insertions?J'utilise Visual Studio 2010, .NET 4.0 et SQL Server 2008r2, au cas où cela ferait une différence.
Comme suggéré par Aaron, une procédure stockée la rendrait plus rapide car elle permet à Sql Server de compiler votre lot SQL. Cependant, vous pouvez toujours opter pour l'une ou l'autre approche: ExecuteScalar
ou ExecuteNonQuery
. À mon humble avis, la différence de performances entre eux est si faible, que l'une ou l'autre méthode est tout aussi "appropriée".
Cela dit, je ne vois pas l'intérêt d'utiliser ExecuteScalar
si vous saisissez la valeur d'identité à partir d'un paramètre de sortie. Dans ce cas, la valeur renvoyée par ExecuteScalar
devient inutile.
Une approche que j'aime car elle nécessite moins de code, utilise ExecuteScalar
sans paramètres de sortie:
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();
}
}
}
Bonne programmation!
EDIT : Notez que nous devons lancer deux fois: de l'objet en decimal
, puis en int
(merci à techturtle pour l'avoir noté).