0

I am just learning to use Parallel.Invoke() and am trying to wrap my mind around returning multiple DataSets() For example, let's take the sample syntax below - how could I use the method ExecuteSqlQuery() for each one of the 3 DataSets() I need returned?

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

My Target Framework for this project is Net Framework 4

2 Answers 2

1

Try this solution and see if it will work in your instance.

Software Cafe

(Please note this is a direct copy/paste in case the site goes down at any time)

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

I do not have a compiler on this machine, but something similar to this should allow you to return a dataset for each stored procedure, or this should at least be a good starting point. Ideally you would want to use a using() statement for each connection to ensure it disposes properly, but again this is a starting point

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) { }
}
Sign up to request clarification or add additional context in comments.

2 Comments

how would I return a dataset with the above syntax?
@RashidInman - see edit. This may not be exact syntax, but should get you pretty close to what you are wanting to achieve.
0

Why don't you use async/await methods and register them into the page in async mode? http://www.asp.net/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45

UPDATE: I will share a sample of doing async processes using ASP.NET WebForms in 4.0. First I define an extension method utility for generating instances of 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);
    }
}

Then, in the aspx file, you need to mark the page with the Async property as true:

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

Then, in your code-behind, just create a Task and register it like this sample:

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

8 Comments

My target framework is .Net Framework 4, is this applicable with this version?
Yes, but it's a little more verbose... you need to make begin/end methods that wraps the task call
over my beginner head on that one
I updated the answer with a sample. I think that your problem is easier to solve using asyncronous programming than parallel programming.
@user2676140 - Try to bind a datatable, not a dataset.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.