SqlCommand
SqlCommand is the object that carries your SQL to the server. Picking the right Execute method makes code simpler and faster.
On this page · 5 min · Beginner
On this page
- In simple words
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 29, 2026
Related tutorials
In simple words#
SqlCommand is the message you speak over the line: the SQL text plus the values (parameters) to use.
- CommandText
- The SQL or procedure name.
- Parameters
- Safe values for the SQL.
- Execute methods
- NonQuery, Scalar, Reader.
Learning objectives#
- Create commands with SQL text or procedure names
- Choose the right Execute method
- Set CommandTimeout
- Reuse a command with different parameter values
Explanation#
CommandText holds the SQL (or a stored procedure name); Connection is where it runs; CommandType is Text (default) or StoredProcedure.
ExecuteNonQuery for INSERT, UPDATE, DELETE and DDL. ExecuteScalar for a single value. ExecuteReader for rows. Each has an Async version.
CommandTimeout (default 30 seconds) limits how long a command waits for SQL Server; 0 means wait forever and should be avoided.
Commands can be reused: change parameter values and execute again — useful in loops.
Code example: The three Execute methods#
await using var conn = new SqlConnection(cs);
await conn.OpenAsync();
// 1. ExecuteNonQuery → rows affected
await using var update = new SqlCommand("UPDATE Products SET Price = Price * 1.05 WHERE CategoryId = @cat", conn);
update.Parameters.Add("@cat", SqlDbType.Int).Value = 1;
int changed = await update.ExecuteNonQueryAsync();
// 2. ExecuteScalar → one value
await using var count = new SqlCommand("SELECT COUNT(*) FROM Products", conn);
int total = (int)(await count.ExecuteScalarAsync())!;
// 3. ExecuteReader → rows
await using var list = new SqlCommand("SELECT TOP (2) Name FROM Products ORDER BY Price DESC", conn) { CommandTimeout = 10 };
await using var r = await list.ExecuteReaderAsync();
while (await r.ReadAsync()) Console.WriteLine(r.GetString(0));
Console.WriteLine(quot;{changed} prices updated, {total} products in total");
Laptop Keyboard 2 prices updated, 3 products in total
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- The UPDATE returns how many rows it changed.
- COUNT(*) returns an int boxed as object, so it is cast.
- The reader streams the two most expensive product names; CommandTimeout is set to 10 seconds.
Real-world use case#
A price-update tool runs one UPDATE per category in a loop, reusing a single command and changing only the @cat value.
Common mistakes#
ExecuteScalar is simpler and avoids reader handling.
A stuck query then hangs forever. Choose a realistic limit.
Best practices#
- Match the Execute method to the result
- Use async methods in web apps
- Always use parameters for values
- Set timeouts deliberately for long reports
Remember this#
NonQuery = changes. Scalar = one value. Reader = rows.
Default CommandTimeout = 30 s.
Reuse a command by changing parameter values.
Practice exercise#
Your task: Use one command in a loop to set Stock = 0 for product Ids 4, 5 and 6.
Show solution
await using var cmd = new SqlCommand("UPDATE Products SET Stock = 0 WHERE Id = @id", conn);
var id = cmd.Parameters.Add("@id", SqlDbType.Int);
foreach (var value in new[] { 4, 5, 6 })
{
id.Value = value;
await cmd.ExecuteNonQueryAsync();
}
Mini quiz#
What is the default CommandTimeout?
Want more? Practise all ADO.NET MCQs · ADO.NET interview questions
My notes#
Saved in this browser.