2

Je me demandais s'il était possible d'appeler plusieurs procédures stockées différentes avec les mêmes paramètres de manière asynchrone en utilisant des tâches et en attendant que tous les résultats reviennent.TPL Tâches et procédures stockées

Je donne les résultats suivants:

private Task<DataTable> DataBaseCall(string procedureName, params Pair[] where) 
    { 
     DataTable data = new DataTable(); 
     SqlConnection connection = new SqlConnection(connStr); 

     SqlCommand command = new SqlCommand(procedureName, connection); 
     connection.Open(); 

     for (int i = 0; i < where.Length; i++) 
     { 
      command.Parameters.Add(where[i].First.ToString(), where[i].Second.ToString()); 
     } 

     var readerTask = Task<SqlDataReader>.Factory.FromAsync(command.BeginExecuteReader, command.EndExecuteReader, null); 
     return readerTask.ContinueWith(t => 
      { 
       var reader = t.Result; 
       try 
       { 
        reader.Read(); 
        data.Load(reader); 
        return data; 
       } 
       finally 
       { 
        reader.Dispose(); 
        command.Connection.Close(); 
        command.Connection.Dispose(); 
        command.Dispose(); 
       } 
      }); 
    } 

que j'appelle avec:

private void SetReportVariables(string reportName, string[] storedProcedureName, string _clientGroup, string _clientCode, string _finYear, string _period) 
    { 
     Task[] tasks = new Task[storedProcedureName.Length]; 

     for (int i = 0; i < storedProcedureName.Length; i++) 
     { 
      List<Pair> parameters = new List<Pair>(); 
      parameters.Add(new Pair("@ClientGroup", _clientGroup)); 
      parameters.Add(new Pair("@ClientCode", _clientCode)); 
      parameters.Add(new Pair("@FinYear", _finYear)); 

      tasks[i] = DataBaseCall(storedProcedureName[i], parameters.ToArray()); 
     } 
     Task.WaitAll(tasks); 

     ...........Do something with the DataTables......... 
    } 

J'ai trois questions.

  1. Quelqu'un peut-il me dire si c'est un bon moyen de le faire?
  2. Une idée est pourquoi ma variable _finYear semble parfois être omise, ce qui provoque une erreur. Puis-je renvoyer le datatable de la tâche?

Merci

Mike

Répondre

0
  1. Il n'y a rien de fondamentalement mauvais dans cette approche.
  2. Vous ne montrez pas d'où provient _finYear dans votre code, mais en fonction du code que vous montrez, je ne vois aucune raison pour qu'il ne soit pas transmis correctement au sproc.
  3. Bien sûr, vous pouvez renvoyer le DataTable comme ça. Il n'est pas sûr d'accéder simultanément à partir de plusieurs threads, mais il peut être transmis à travers les threads sans problème.

Le seul bug mineur dans votre code est que vous devriez avoir une autre try/finally dans votre logique de gestion suite, car il est possible pour t.Result de lancer une exception s'il y avait un problème avec l'appel async à Begin/EndExecuteReader et qui ne vous laissez pas éliminer la commande et la connexion. Donc, ce serait mieux:

readerTask.ContinueWith(t =>    
{     
    try 
    { 
     var reader = t.Result;     

     try     
     {      
      reader.Read(); 
      data.Load(reader); 

      return data; 
     } 
     finally 
     {      
      reader.Dispose(); 
     }    
    } 
    finally 
    { 
     command.Connection.Close(); 
     command.Connection.Dispose(); 
     command.Dispose();     
    } 
}); 
+0

Salut Merci pour la réponse. J'ai ajouté comment je passe les variables ci-dessus. Je viens de passer un tableau de noms de proc stockés et les trois variables en tant que chaînes, mais pour une raison quelconque, je reçois une erreur System.AggregateException que _finYear est requis par la procédure stockée. Bizarre! – Beats

+0

La seule conjecture que je peux trouver est en quelque sorte que vous avez une valeur nulle pour _finYear. Si vous exécutez sous le débogueur, il doit interrompre l'exception lorsqu'il se produit et vous pouvez vérifier la valeur de _finYear. –