Problem
I’d like a review of this implementation of Async in ASP.NET 2.0 web form page below. Let me know if I am missing something.
AsyncPagesASPNET20.aspx
<%@ Page Language="C#" Async="true" AutoEventWireup="true" CodeFile="AsyncPagesASPNET20.aspx.cs" Inherits="AsyncPagesASPNET20" %>
AsyncPagesASPNET20.aspx.cs
public partial class AsyncPagesASPNET20 : System.Web.UI.Page
{
private string queryCustomerSelect = "SELECT FirstName, LastName FROM SalesLT.Customer";
private DataAccess dataAccess = new DataAccess(WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.PreRenderComplete += AsyncPage_PreRenderComplete;
AddOnPreRenderCompleteAsync(new BeginEventHandler(BeginAsyncOperation), new EndEventHandler(EndAsyncOperation));
}
}
private void EndAsyncOperation(IAsyncResult ar)
{
Trace.Write("EndAsyncOperation...");
this.dataAccess.EndAsyncSelect(ar);
}
private IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object extraData)
{
Trace.Write("BeginAsyncOperation...");
return dataAccess.BeginAsyncSelect(sender, e, cb, extraData, this.queryCustomerSelect);
}
void AsyncPage_PreRenderComplete(object sender, EventArgs e)
{
this.GridView1.DataSource = this.dataAccess.reader;
this.GridView1.DataBind();
}
public override void Dispose()
{
this.dataAccess.Dispose();
}
}
DataAccess.cs
public class DataAccess : IDisposable
{
string connectionString = string.Empty;
private SqlConnection connection;
private SqlCommand command;
public SqlDataReader reader;
public DataAccess(string connectionString)
{
this.connectionString = connectionString;
this.connection = new SqlConnection(this.connectionString);
this.command = new SqlCommand();
}
public IAsyncResult BeginAsyncSelect(object sender, EventArgs e, AsyncCallback cb, object extraData, string query)
{
this.command.CommandText = query;
this.command.CommandType = CommandType.Text;
this.command.Connection = this.connection;
this.connection.Open();
return this.command.BeginExecuteReader(cb, extraData);
}
public void EndAsyncSelect(IAsyncResult ar)
{
this.reader = this.command.EndExecuteReader(ar);
}
public SqlDataReader SelectSync(string query)
{
this.command.CommandText = query;
this.command.Connection = connection;
this.connection.Open();
this.command.Connection = connection;
return this.command.ExecuteReader();
}
#region IDisposable Members
public void Dispose()
{
if (this.connection != null)
{
this.connection.Close();
}
}
#endregion
}
Solution
Overall a very cleanly written class. It is easy to follow and understand.
A couple of suggestions though.
Make the reader class variable a Property with a private setter. This will eliminate the ability to reassign it from outside of the class. I would also rename it Reader to fit with C# coding standards.
Most C# coding standards I have read suggest prefixing private class variables with a _. This will allow you to remove the this. statement whenever you need to access one of the class variables. I think doing that will make you code much easier to read.
I’m not sure what the SelectSync method is used for. I see it as a way to do a non-async query into the database. If that is the case, I would move it to a different class as it interferes with the async nature of the one you have written. Maybe rename this class to DataAccessAsync, and have a second one DataAccess? Its hard to say without an example of a call to that method.
I can’t see much more at this point.