SqlConnection
SqlConnection represents a session with SQL Server. Opening it late and closing it early is the most important habit in ADO.NET.
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#
SqlConnection is the phone line itself. Pick up as late as possible, hang up as soon as you’re done — using does the hanging up for you.
- SqlConnection
- A session with SQL Server.
- Open / OpenAsync
- Start the session.
- using
- Guarantees the connection is closed.
Learning objectives#
- Open and close connections correctly
- Use using declarations and await using
- Check connection state and server info
- Handle connection failures
Explanation#
Creating a SqlConnection is cheap; Open is where the real work happens (or where a pooled connection is reused).
Use using var (or await using var in async code). Dispose closes the connection and returns it to the pool.
Open as late as possible — just before executing — and let it close as soon as the work is done. Do not keep connections in fields or static variables.
If the server cannot be reached, Open throws SqlException after Connect Timeout (default 15 seconds).
Code example: Opening a connection safely#
using Microsoft.Data.SqlClient;
const string cs = "Server=localhost;Database=ShopDB;Integrated Security=True;TrustServerCertificate=True;Connect Timeout=5;";
try
{
await using var conn = new SqlConnection(cs);
Console.WriteLine(quot;Before: {conn.State}");
await conn.OpenAsync();
Console.WriteLine(quot;After: {conn.State}");
Console.WriteLine(quot;Server: {conn.DataSource}, version {conn.ServerVersion}, database {conn.Database}");
}
catch (SqlException ex)
{
Console.WriteLine(quot;Could not connect (error {ex.Number}): {ex.Message}");
}
Before: Closed After: Open Server: localhost, version 16.00.1000, database ShopDB
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 connection starts Closed.
- OpenAsync opens it (or takes one from the pool) without blocking the thread.
- Properties expose the server, version and database.
- await using disposes the connection at the end of the try block.
- SqlException.Number identifies the problem (e.g. 18456 = login failed).
Real-world use case#
A health check endpoint opens a connection and runs SELECT 1 to confirm the database is reachable before the load balancer sends traffic.
Common mistakes#
SqlConnection is not thread-safe. Create one per operation; pooling makes this cheap.
Idle open connections waste server resources and break when the network blips.
Best practices#
- One connection per unit of work
- await using in async code
- Open late, close early
- Log SqlException.Number with errors
Remember this#
Create cheap, Open real.
using = always closed, even on errors.
Not thread-safe → never share.
Practice exercise#
Your task: Write a method IsDatabaseUpAsync that returns true if SELECT 1 succeeds.
Show solution
static async Task<bool> IsDatabaseUpAsync(string cs)
{
try
{
await using var conn = new SqlConnection(cs);
await conn.OpenAsync();
await using var cmd = new SqlCommand("SELECT 1", conn);
return (int)(await cmd.ExecuteScalarAsync())! == 1;
}
catch (SqlException) { return false; }
}
Mini quiz#
What does disposing a pooled SqlConnection do?
Want more? Practise all ADO.NET MCQs · ADO.NET interview questions
My notes#
Saved in this browser.