【问题标题】:C# asynch SQL inside singleton and delegates单例和委托中的 C# 异步 SQL
【发布时间】:2012-09-13 14:40:45
【问题描述】:

我正在尝试构建一个负责数据库所有操作的类。

从这里使用单例模式:http://codebender.denniland.com/a-singleton-base-class-to-implement-the-singleton-pattern-in-c/

我已经建立了一个这样的类:

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");
        }
    }

在我的主课中,我是这样使用的:

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

但这只会给我我的消息框。

我想做的是在我的主类中声明将在 SQL 查询返回某些内容后调用的函数。

我认为最好的方法是使用事件,但我不知道如何正确地做到这一点。

我想在我的主课上做这样的事情:

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

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

这样我就可以指定在 SQL 调用完成后调用的函数。

我不知道这是否是最好的方法,所以欢迎任何 cmets、建议和解决方案。

我想要实现的是让一个类负责异步调用 SQL 并将数据传递给将处理它的其他函数。

【问题讨论】:

  • 你看过代表吗?
  • 顺便说一句:单身是邪恶的:c2.com/cgi/wiki?SingletonsAreEvil
  • 是的,我知道我可以使用委托,但我在尝试时遇到了问题。我也想知道我的想法好不好。我应该使用单例以及如何从中调用方法。当我调用BeginExecuteReader 时,我必须以某种方式传递在执行 sql 后必须调用的函数名称。其背后的想法是能够调用 10 个查询到 sql server 以便它们都将执行。

标签: c# asynchronous


【解决方案1】:
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+")");
}

【讨论】:

  • 感谢您的快速回答:) 但是如何将callback 传递给我的HandleCallback 函数。在我的单例中可见的函数是 loadData,它启动我的 sql 查询,查询完成后调用HandleCallback,在那里我检查我的查询是否执行成功。如果否,我想显示错误消息,如果是,则从我的主类调用我的函数。我知道这听起来可能很傻,但我不知道如何将回调函数传递给HandleCallback。给您添麻烦了:)
  • 使用类作为 BeginExecuteReader 的参数,而不是 cmd,其中包含 SqlCommand 和回调。然后,您将在 HandleCallback 方法中同时使用两者。
  • 你能告诉我如何修改我的两个函数loadDataHandleCallback 来完成这个吗?
  • 看看我的编辑。从中清楚吗?您可以在 HandleCallback 中提供一个参数,即 IAsyncResult.AsyncState。而不是只给 SqlCommand 给它一个更复杂的对象,它包含命令和回调。
  • 越来越清楚了:) 还有一件事,如何声明ClassWithCommandAndCallback?有2个回调会更好吗?一个会在 sql 完成且没有错误时处理数据,第二个会在发生任何错误时调用?
猜你喜欢
  • 2010-11-27
  • 2012-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多