【问题标题】:Use 1 DataReader For Multiple Database Calls使用 1 个 DataReader 进行多个数据库调用
【发布时间】:2016-03-11 19:00:00
【问题描述】:

我只是在学习使用Parallel.Invoke() 并试图将我的想法围绕返回多个DataSets() 例如,让我们采用下面的示例语法 - 我如何对 3 个中的每一个都使用方法 ExecuteSqlQuery() DataSets()我需要退货吗?

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
    Parallel.Invoke(
        new Action(GetFirstGraders),
        new Action(GetSecondGraders),
        new Action(GetThirdGraders)
        );
  }
}

private void GetFirstGraders()
{
  datasetttt1stgrade = FirstGraders();
  gv1.DataSource = datasetttt1stgrade;
  gv1.DataBind();
}

private void GetSecondGraders()
{
  datasetttt2ndgrade = SecondGraders();
  gv2.DataSource = datasetttt2ndgrade;
  gv2.DataBind();
}

private void GetThirdGraders()
{
  datasetttt3rdgrade = ThirdGraders();
  gv3.DataSource = datasetttt3rdgrade;
  gv3.DataBind();
}

public DataSet FirstGraders()
{
  datasetttt = new DataSet();
  SqlQueryBuilder = new StringBuilder();
  SqlQueryBuilder.Append("exec FirstGraders ");
  datasetttt = ExecuteSqlQuery(databaseConnection, SqlQueryBuilder.ToString());
  datagridInfo.DataSource = datasetttt;
  datagridInfo.DataBind();
}

public DataSet SecondGraders()
{
  datasetttt = new DataSet();
  SqlQueryBuilder = new StringBuilder();
  SqlQueryBuilder.Append("exec SecondGraders ");
  datasetttt = ExecuteSqlQuery(databaseConnection, SqlQueryBuilder.ToString());
  datagridInfo.DataSource = datasetttt;
  datagridInfo.DataBind();
}

public DataSet ThirdGraders()
{
  datasetttt = new DataSet();
  SqlQueryBuilder = new StringBuilder();
  SqlQueryBuilder.Append("exec ThirdGraders ");
  datasetttt = ExecuteSqlQuery(databaseConnection, SqlQueryBuilder.ToString());
  datagridInfo.DataSource = datasetttt;
  datagridInfo.DataBind();
}

public DataSet ExecuteSqlQuery(string connectionString, string sqlQuery)
{
  try
  {           
    connstring = System.Configuration.ConfigurationManager.AppSettings[connectionString].ToString();    
    dbconn = new SqlConnection(connstring);
    cm = new SqlCommand(sqlQuery, dbconn);
    dbconn.Open();
    cm.CommandTimeout = 0;   
    datasetttt = new DataSet();
    da = new SqlDataAdapter(cm);            
    da.Fill(datasetttt, "Data");
    return datasetttt;
  }
  catch (Exception exception) { throw exception; }
  finally
  {
    dbconn.Close();
    cm.Dispose();
    da.Dispose();
  }
}

我的这个项目的目标框架是 Net Framework 4

【问题讨论】:

    标签: c# asp.net webforms parallel.invoke


    【解决方案1】:

    试试这个解决方案,看看它是否适用于您的实例。

    Software Cafe

    (请注意这是直接复制/粘贴,以防网站随时出现故障)

    protected void Page_Load(object sender, EventArgs e)
    {
      SqlConnection cnn1 = new SqlConnection("Your connection string");
      SqlConnection cnn2 = new SqlConnection("Your connection string");
      SqlCommand cmd1;
      SqlCommand cmd2;
      IAsyncResult result1;
      IAsyncResult result2;
      SqlDataReader reader1;
      SqlDataReader reader2;
    
      try
      {
        cnn1.Open();
    
        cmd1 = new SqlCommand("SP1", cnn1);
        cmd1.CommandType = System.Data.CommandType.StoredProcedure;
        result1 = cmd1.BeginExecuteReader(CommandBehavior.SingleRow);
    
        cnn2.Open();
        cmd2 = new SqlCommand("SP2", cnn2);
        cmd2.CommandType = System.Data.CommandType.StoredProcedure;
        result2 = cmd2.BeginExecuteReader(CommandBehavior.SingleRow);
    
        reader1 = cmd1.EndExecuteReader(result1);
    
        if (reader1.Read())
        {
            Literal1.Text = reader1[0].ToString();
        }
    
        reader1.Close();
    
        reader2 = cmd2.EndExecuteReader(result2);
    
        if (reader2.Read())
        {
            Literal2.Text = reader2[0].ToString();
        }
    
        reader2.Close();
      }
      catch (Exception ex)
      {  
        // raise an exception or do whatever logic you want
      }
      finally
      {
        if (cnn1.State != System.Data.ConnectionState.Closed)
            cnn1.Close();
    
        if (cnn2.State != System.Data.ConnectionState.Closed)
            cnn2.Close();
      }
    }
    

    我在这台机器上没有编译器,但是与此类似的东西应该允许您为每个存储过程返回一个数据集,或者这至少应该是一个很好的起点。理想情况下,您希望为每个连接使用 using() 语句以确保其正确处理,但这也是一个起点

    protected void Page_Load(object sender, EventArgs e)
    {
    SqlCommand _sqlCommand1;
    SqlCommand _sqlCommand2;
    SqlCommand _sqlCommand3;
    DataSet ds1 = new DataSet();
    DataSet ds2 = new DataSet();
    DataSet ds2 = new DataSet();
    SqlDataAdapter _sqlDataAdapter1 = new SqlDataAdapter();
    SqlDataAdapter _sqlDataAdapter2 = new SqlDataAdapter();
    SqlDataAdapter _sqlDataAdapter3 = new SqlDataAdapter();
    SqlConnection _sqlDatabaseConnection1;
    SqlConnection _sqlDatabaseConnection2;
    SqlConnection _sqlDatabaseConnection3;
    
    try
    {
      _connectionString = System.Configuration.ConfigurationManager.AppSettings[connectionString].ToString();
      _sqlDatabaseConnection1 = new SqlConnection(_connectionString);
      _sqlCommand1 = new SqlCommand("SP1", _sqlDatabaseConnection1);
      _sqlDatabaseConnection1.Open();
      _sqlCommand1.CommandTimeout = 0;
      ds1 = new DataSet();
      _sqlDataAdapter1 = new SqlDataAdapter(_sqlCommand1);
      _sqlDataAdapter1.Fill(ds1, "Data");
      return ds1;
      _sqlDatabaseConnection1.Close();
      _sqlCommand1.Dispose();
      _sqlDataAdapter1.Dispose();
      _connectionString = System.Configuration.ConfigurationManager.AppSettings[connectionString].ToString();
      _sqlDatabaseConnection2 = new SqlConnection(_connectionString);
      _sqlCommand2 = new SqlCommand("SP2", _sqlDatabaseConnection1);
      _sqlDatabaseConnection2.Open();
      _sqlCommand2.CommandTimeout = 0;
      ds2 = new DataSet();
      _sqlDataAdapter2 = new SqlDataAdapter(_sqlCommand1);
      _sqlDataAdapter2.Fill(ds2, "Data");
      return ds2;
      _sqlDatabaseConnection2.Close();
      _sqlCommand2.Dispose();
      _sqlDataAdapter2.Dispose();   
      _connectionString = System.Configuration.ConfigurationManager.AppSettings[connectionString].ToString();
      _sqlDatabaseConnection3 = new SqlConnection(_connectionString);
      _sqlCommand3 = new SqlCommand("SP3", _sqlDatabaseConnection1);
      _sqlDatabaseConnection3.Open();
      _sqlCommand3.CommandTimeout = 0;
      ds2 = new DataSet();
      _sqlDataAdapter3 = new SqlDataAdapter(_sqlCommand1);
      _sqlDataAdapter3.Fill(ds3, "Data");
      return ds3;
      _sqlDatabaseConnection3.Close();
      _sqlCommand3.Dispose();
      _sqlDataAdapter3.Dispose();
    
    }
    catch (Exception ex) { }
    }
    

    【讨论】:

    • 如何返回具有上述语法的数据集?
    • @RashidInman - 见编辑。这可能不是确切的语法,但应该让您非常接近您想要实现的目标。
    【解决方案2】:

    为什么不使用 async/await 方法并以异步模式将它们注册到页面中? http://www.asp.net/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45

    更新:我将分享一个在 4.0 中使用 ASP.NET WebForms 进行异步处理的示例。首先,我定义了一个扩展方法实用程序,用于生成 PageAsyncTask 的实例:

    public static class PageAsyncTaskGenerator
    {
        public static PageAsyncTask ToPageAsyncTask(this Task task, Action<IAsyncResult> onTimeout = null)
        {
            Func<Task> func = () => task;
            return new PageAsyncTask(
                (sender, e, cb, extraData) => func.BeginInvoke(cb, extraData),
                ar => func.EndInvoke(ar).Wait(),
                ar =>
                {
                    if (onTimeout != null)
                    {
                        onTimeout(ar);
                    }
                }, 
                null);
        }
    }
    

    然后,在 aspx 文件中,需要将具有 Async 属性的页面标记为 true

    <%@ Page Language="C#" AutoEventWireup="true" Async="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
    

    然后,在您的代码隐藏中,只需创建一个任务并像此示例一样注册它:

    protected void Page_Load(object sender, EventArgs e)
    {
        RegisterAsyncTask(LoadDataAsync().ToPageAsyncTask());
    }
    
    private Task LoadDataAsync()
    {
        var t1 = ExecuteQueryAsync(databaseConnection, "exec FirstGraders ");
        var t2 = ExecuteQueryAsync(databaseConnection, "exec SecondGraders ");
        var t3 = ExecuteQueryAsync(databaseConnection, "exec ThirdGraders ");
        return Task.Factory.ContinueWhenAll(new[] { t1, t2, t3 }, _ => {
            gv1.DataSource = t1.Result;
            gv1.DataBind();
            gv2.DataSource = t2.Result;
            gv2.DataBind();
            gv3.DataSource = t3.Result;
            gv3.DataBind();
        });
    }
    
    private Task<DataSet> ExecuteSqlQueryAsync(string connectionString, string sqlQuery)
    {
        return Task.Factory.StartNew(
        () =>
        {
            try
        {
            connstring = System.Configuration.ConfigurationManager.AppSettings[connectionString].ToString();
            dbconn = new SqlConnection(connstring);
            cm = new SqlCommand(sqlQuery, dbconn);
            dbconn.Open();
            cm.CommandTimeout = 0;
            datasetttt = new DataSet();
            da = new SqlDataAdapter(cm);
            da.Fill(datasetttt, "Data");
            return datasetttt;
        }
        catch (Exception exception) { throw exception; }
        finally
        {
            dbconn.Close();
            cm.Dispose();
            da.Dispose();
        }
        });
    }
    

    【讨论】:

    • 我的目标框架是.Net Framework 4,这个版本适用吗?
    • 是的,但它有点冗长......你需要制作包装任务调用的开始/结束方法
    • 在我的初学者头上那个
    • 我用示例更新了答案。我认为使用异步编程比并行编程更容易解​​决您的问题。
    • @user2676140 - 尝试绑定数据表,而不是数据集。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    • 2013-08-01
    • 2014-01-18
    • 2016-04-19
    • 2019-04-23
    相关资源
    最近更新 更多