Usually when I am coding in C# I either write my SqlDataReader one of two ways:
reader.Read();
if (reader.HasRows)
{
// Code here
}
reader.Close();
Or:
while (reader.Read())
{
// Code here
}
In the first instance I open the SqlDataReader and close it. The second one I am just called reader.Read() in a while loop.
My question is: Does calling reader.Read() close itself after it has read all data? Or should I still call reader.Close()?
Does calling reader.Read() close itself after it has read all data?
No. Read() method just moves cursor to the next row. The default position is before the first record. That's why you have to use this method to read any data in your reader.
should I still call a reader.Close();
Yes but instead of that, use using statement to dispose your SqlDataReader automatically.
using(var reader = command.ExecuteReader())
{
while (reader.Read())
{
// Code here
}
} <-- your reader will be disposed here.
Or:
using(SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// Code here
}
}
...which calls IDisposable.Dispose if assigned object inside the using statement is an IDisposable when the using block ends (if it's not an IDisposable compiler will cry!), which is a syntactic sugar of:
SqlDataReader reader = cmd.ExecuteReader();
try
{
while (reader.Read())
{
// Code here
}
}
finally
{
if(reader != null)
{
reader.Dispose();
}
}
You can either call Close or Dispose, but use the using approach always in order to avoid leaving a disposable object non disposed if an exception is thrown before the Close or Dispose is called.
As some commenter has said, using block is also for who's vague and this way it's not possible that you forgot to call Dispose as it's implicitly-called.
BTW, this is subjective because who misses a Dispose call probably won't use using block... From my experience, there're still a lot of .NET developers who don't understand the importance of why an object implement IDisposable.
It's not just a cosmetic detail: if a type implements IDisposable is because it is mandatory to call Dispose either when you instantiate the IDisposable type and you don't need it anymore or during a specific moment in the application life-cycle. But either way, the IDisposable.Dispose call is mandatory.
My two cents about the topic will be that using block is a good way of not having to explain low-level details to unexperienced .NET developers. It's easier to define a team development rule / guide where you may state that code review won't pass if a IDisposable object isn't instantiated within an using block without a clear justification.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With