C# asynch SQL inside singleton and delegates

2019-02-26 14:03发布

I'm trying to build a class that will be responsible for all operations on database.

Using singleton pattern from here: http://codebender.denniland.com/a-singleton-base-class-to-implement-the-singleton-pattern-in-c/

I've build a class like so:

class DB : SingletonBase<DB>
    {

        public static readonly string SqlConnectionString  = @"Data Source=MYDB;Initial Catalog=PRODUCTS;Integrated Security=True;Asynchronous Processing=true;";

        private DB()
        {
        }

        public void loadData()
        {
            SqlConnection conn = new SqlConnection(SqlConnectionString);
            SqlCommand cmd = conn.CreateCommand();
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "STATISTICS_1";

            cmd.Connection = conn;
            conn.Open();
            IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(HandleCallback), cmd, CommandBehavior.CloseConnection);
        }

        private void HandleCallback(IAsyncResult result)
        {
            SqlDataReader dr;
            SqlCommand _this = (SqlCommand)result.AsyncState;

            if (result.IsCompleted)
            {
                dr = _this.EndExecuteReader(result);
            }
            else
                dr = null;

            DataTable dt = new DataTable();
            dt.Load(dr);
            dr.Close();
            MessageBox.Show("loaded");
        }
    }

In my main class I'm using this like so:

    private void loadStatistics(object sender, EventArgs e)
    {
        showStatus("loading data");
        DB.Instance.loadData();
    }

But this will give me only my message box.

What I would like to do is to declare function in my main class that will be called after SQL query return something.

I think that the best way would by using events, but I don't know how to do that proper way.

I would like to do something like this in my main class:

    private void loadCompleted(string msg)
    {
        MessageBox.Show(msg);
    }

    private void loadStatistics(object sender, EventArgs e)
    {
        showStatus("loading data");
        DB.Instance.loadData(loadCompleted);
    }

So that I can specify function that will be called after SQL call is finished.

I don't know if this is the best way of doing this, so any comments, suggestions and solutions are welcome.

What I would like to achieve is to have one class responsible for calling SQL asynchronously and passing data to other functions that will process it.

1条回答
老娘就宠你
2楼-- · 2019-02-26 14:49
public delegate void NotifyCallback(string message);    

public class ClassWithCommandAndCallback 
{
  public SqlCommand Sql;
  public NotifyCallback Callback;
}

public void loadData(NotifyCallback callback)
{
  ClassWithCommandAndCallback ar = new ClassWithCommandAndCallback();
  ar.Sql = cmd;
  ar.Callback = callback;
  IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(HandleCallback), ar, CommandBehavior.CloseConnection);
}

private void HandleCallback(IAsyncResult result)
{
  ClassWithCommandAndCallback ar = (ClassWithCommandAndCallback)result.AsyncState;

  ar.Callback("loaded (SQL was: "+ar.Sql+")");
}
查看更多
登录 后发表回答