SqlCommand Close and Dispose - which to call?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
With ADO.NET resource handling, developers often ask whether SqlCommand.Close() or Dispose() should be called. The short answer is that SqlCommand is normally disposed, while Close() is more relevant to readers and connections. Understanding which object actually owns the expensive resource avoids redundant cleanup code and makes data-access code safer.
What SqlCommand Actually Owns
SqlCommand represents the SQL text, parameters, and execution context for a database operation. It cooperates with a SqlConnection, and sometimes with a SqlDataReader, but it is not the network connection itself.
Typical usage:
In this flow, the important lifetime boundary is usually the connection, not the command.
Close() Versus Dispose()
For SqlCommand, Dispose() is the meaningful cleanup method. Close() is not the method you usually think about for commands. In day-to-day ADO.NET work:
- call
Dispose()onSqlCommand, usually viausing - call
Close()orDispose()onSqlConnectionif not usingusing - call
Close()orDispose()onSqlDataReaderwhen finished reading
The reason this feels confusing is that many examples mix up cleanup responsibilities across related objects.
Best Practice: Use using
The cleanest pattern is scoped disposal.
This ensures Dispose() is called automatically even if an exception occurs. It also removes the need to remember separate manual cleanup calls.
Reader Ownership Is More Important Than Command Close
When a command returns a SqlDataReader, the reader can keep the connection busy until it is closed or disposed.
In this example, failing to dispose reader is usually a bigger problem than worrying about command.Close().
Manual Cleanup When using Is Not Possible
If you must manage lifetimes manually, dispose in reverse order of usage.
This is still valid, but more error-prone than scoped disposal.
Why Redundant Close() Calls Usually Add No Value
Some code bases call both Close() and Dispose() on every object. That is usually noise, not safety. Dispose() already represents final cleanup for disposable objects. Repeating both calls makes intent less clear and encourages copy-paste patterns rather than ownership-based reasoning.
If you see both everywhere, simplify where possible and let using express lifetime clearly.
CommandBehavior.CloseConnection
One special case is reader-driven connection cleanup.
Here, closing the reader also closes the connection. This can be useful, but it should be used intentionally because it couples reader lifetime to connection lifetime.
Common Pitfalls
- Calling
Close()onSqlCommandout of habit while ignoring reader or connection disposal. - Manually cleaning up every object instead of using
using. - Forgetting that an open
SqlDataReadercan hold the connection busy. - Assuming garbage collection will promptly release database-related resources.
- Writing redundant
Close()plusDispose()sequences that obscure real ownership.
Summary
- For
SqlCommand,Dispose()is the cleanup action that matters most. - '
Close()is more relevant to connections and readers than to commands.' - Prefer
usingso disposal happens automatically and safely. - Focus resource management on the objects that actually hold expensive state.
- Keep cleanup code simple, explicit, and based on ownership rather than habit.

