AsyncPages in ASP.NET 2.0 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

&lt;%@ Page Language="C#" Async="true" AutoEventWireup="true" CodeFile="AsyncPagesASPNET20.aspx.cs" Inherits="AsyncPagesASPNET20" %&gt;


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
}
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.