I have a for loop and inside the for loop I'm calling a DB method that brings data from SQL server. It is a lot and it takes like 15 sec. I was thinking that maybe I can use task to optimize it.
The problem is when I use the task, and I wait for all task. It's giving me problems related with concurrency, some times that the reader is closed, other issues with the connection.
I have never had the need to think on this scenario, would you mind checking my ADODB code to see if there is a way that I can use the task without having issues of concurrency?
public IBudget getBudget(int company, string tablename, int year, string account)
{
SqlCommand cmd1;
int x = 1;
if (tablename == "Actual")
x = -1;
Budget item;
item = new Budget();
try
{
cmd1 = new SqlCommand("sp_Dashboard_GetBudget", cnxCRM);
cmd1.CommandType = CommandType.StoredProcedure;
cmd1.Parameters.AddWithValue("@coNum", company);
cmd1.Parameters.AddWithValue("@tablename", tablename);
cmd1.Parameters.AddWithValue("@year", year);
cmd1.Parameters.AddWithValue("@account", account);
if( cnxCRM.State == ConnectionState.Closed)
cnxCRM.Open();
SqlDataReader sqlDataReader = cmd1.ExecuteReader();
if (sqlDataReader.HasRows)
{
while (sqlDataReader.Read())
{
item.GLAccount = sqlDataReader["GLAccountNo"].ToString();
item.Month1 = float.Parse(sqlDataReader["Month1"].ToString()) * x;
item.Month2 = float.Parse(sqlDataReader["Month2"].ToString())* x;
item.Month3 = float.Parse(sqlDataReader["Month3"].ToString())* x;
item.Month4 = float.Parse(sqlDataReader["Month4"].ToString())* x;
item.Month5 = float.Parse(sqlDataReader["Month5"].ToString())* x;
item.Month6 = float.Parse(sqlDataReader["Month6"].ToString())* x;
item.Month7 = float.Parse(sqlDataReader["Month7"].ToString())* x;
item.Month8 = float.Parse(sqlDataReader["Month8"].ToString())* x;
item.Month9 = float.Parse(sqlDataReader["Month9"].ToString()) * x;
item.Month10 = float.Parse(sqlDataReader["Month10"].ToString())* x;
item.Month11 = float.Parse(sqlDataReader["Month11"].ToString())* x;
item.Month12 = float.Parse(sqlDataReader["Month12"].ToString()) * x;
}
}
}
catch (Exception ex)
{
if (cnxCRM.State == ConnectionState.Open)
{
cnxCRM.Close();
throw ex;
}
}
finally
{
//this.cnxCRM.Close();
}
return item;
}
This is the code where I create the task and wait for all of them. The function data.getBudget is the one that is giving me issues:
var getBudgetTask = new List<Task>();
foreach (Checkbook c in list)
{
var getAcc = Task.Run(() =>
{
List<IAccount> accLst = new List<IAccount>();
accLst = data.getAccounts(c.CheckbookID).ToList();
///for each account get the budget
foreach (IAccount acc in accLst)
{
IBudget actual = data.getBudget(c.CompanyNumber, "Actual", DateTime.Now.Year, acc.GLAccount);
IBudget budget = data.getBudget(c.CompanyNumber, "Budget", DateTime.Now.Year, acc.GLAccount);
for (int i = 1; i <= 12; i++)
{
string name = "Month" + i;
final[i - 1].Actual += decimal.Parse(budgetvariable.GetProperty(name).GetValue(actual).ToString());
final[i - 1].Budget += decimal.Parse(budgetvariable.GetProperty(name).GetValue(budget).ToString());
}
}
});
getBudgetTask.Add(getAcc);
}
await Task.WhenAll(getBudgetTask);
Thank you and I will really appreciatte the help.