SqlDataReader
manual resource management
C# programming
data handling
.NET development

Is it necessary to manually close and dispose of SqlDataReader?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Yes, a SqlDataReader should be closed or disposed promptly when you are done reading rows. In idiomatic C#, you normally satisfy that requirement with using, which means you rarely need to call both Close() and Dispose() yourself.

Use using for the Normal Reader Lifetime

SqlDataReader keeps database resources active while it is open. The connection stays occupied, the server may still be streaming results, and your connection pool does not get that connection back until the reader is released.

That is why the standard pattern is to scope the reader tightly:

csharp
1using System;
2using System.Data.SqlClient;
3
4class Program
5{
6    static void Main()
7    {
8        var connectionString = "Server=.;Database=master;Trusted_Connection=True;";
9
10        using var connection = new SqlConnection(connectionString);
11        connection.Open();
12
13        using var command = new SqlCommand(
14            "SELECT TOP 3 name FROM sys.databases ORDER BY name",
15            connection
16        );
17
18        using var reader = command.ExecuteReader();
19
20        while (reader.Read())
21        {
22            Console.WriteLine(reader.GetString(0));
23        }
24    }
25}

When execution leaves the scope, Dispose() is called automatically even if an exception is thrown. That is the main reason using is preferred over manual cleanup code scattered through the method.

Know When an Explicit Close() Helps

Calling Close() manually is still valid when you want to release the reader before the end of the scope. For example, maybe you need the same connection for a second command later in the method and you want the reader gone immediately.

csharp
1using var connection = new SqlConnection(connectionString);
2connection.Open();
3
4using var command = new SqlCommand("SELECT TOP 1 name FROM sys.databases", connection);
5using var reader = command.ExecuteReader();
6
7if (reader.Read())
8{
9    Console.WriteLine(reader.GetString(0));
10}
11
12reader.Close();
13
14using var countCommand = new SqlCommand("SELECT COUNT(*) FROM sys.databases", connection);
15Console.WriteLine(countCommand.ExecuteScalar());

In this pattern, Close() shortens the lifetime deliberately. The later Dispose() at the end of the scope is fine, but it is not a separate requirement you need to think about. The important thing is that the live reader is released as soon as you stop using it.

The reader depends on an open connection. While the reader is active, some providers limit what else can happen on that same connection. Even when another command would be legal, keeping the reader open longer than necessary is still poor resource hygiene.

You may also encounter:

csharp
var reader = command.ExecuteReader(CommandBehavior.CloseConnection);

With that option, closing the reader also closes the connection. That can be convenient in narrowly scoped code, but it changes the cleanup behavior, so use it only when the connection lifetime really should follow the reader lifetime.

The practical rule is simple: keep both the reader scope and the connection scope as small as the code allows.

Common Pitfalls

The most common mistake is forgetting to dispose the reader at all. That can leave connections busy longer than expected and create avoidable pressure on the connection pool.

Another frequent mistake is manually calling both Close() and Dispose() everywhere out of habit. If you are already using using, that extra ceremony does not add safety.

A third issue is doing unrelated work while the reader is still open. Read the rows you need, map them, and release the reader. Do not keep it alive while you run business logic, call external services, or build a response object in several distant steps.

Summary

  • A SqlDataReader must be released promptly because it holds live database resources.
  • In normal C# code, using is the preferred way to close and dispose it safely.
  • Call Close() manually only when you need to end the reader earlier than the scope would.
  • An open reader can delay connection reuse and reduce throughput.
  • Keep reader and connection lifetimes tight for predictable resource behavior.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.