I was just wondering about the correct way to return a reader from a class?
My code below works, but I’m unsure if this is correct.
Also. I can’t close the the connection in my class method and still access it from my ascx page, is
that OK?
// In my class I have the following method to return the record/reader — it’s a single record in this case.
public SqlDataReader GetPost()
{
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("con_spPost", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@blogid", blogid);
try
{
conn.Open();
return cmd.ExecuteReader();
}
finally
{
// conn.Close();
}
}
//I then call the GetPost method in my ascx page like so:
protected void Page_Load(object sender, EventArgs e)
{
//instantiate our class
MyClass DB = new MyClass();
//pass in the id of the post we want to view
DB.PostID = Int32.Parse(Request.QueryString["p"]);
///call our GetPost method
SqlDataReader reader = DB.GetPost();
//output the result
reader.Read();
this.viewpost.InnerHtml = "<span id='post1_CreatedDate'>" + reader["CreatedDate"].ToString() + "</span><br>";
this.viewpost.InnerHtml += "<span class='blogheads'>" + reader["BlogTitle"].ToString() + "</span><p><p>";
this.viewpost.InnerHtml += reader["BlogText"].ToString();
reader.Close();
}
I’d appreciate any comments on my code or tips, thanks.
Melt
Generally speaking it’s fine to return a reader from a method, but the reader’s consumer needs to take control of all the disposable objects that will be used during the reader’s lifetime.
To do this, you’d pass an
IDbConnectioninto theGetPostmethod, then make sure your caller disposes both the connection and reader. Theusingkeyword is the most convenient way to do this:As others have pointed out, this starts to clutter your application’s presentation layer with way too much data-access infrastructure – so it isn’t appropriate here. Until you find yourself with a performance problem or need to display an unreasonable amount of data, you shouldn’t be handling data readers in your presentation layer. Just make
DB.GetPostreturn a string, and encapsulate all the data-access code in there.