J'ai un problème
Je cherche à reproduire quelque chose comme plusieurs appels de procédure stockée (sp) dans mon code c#, mais je veux le faire de manière asynchrone.
Exemple TSQL : (Execute sp @key = 15072000173475; Execute sp @key = 15072000173571; ... Execute sp @key = n;
)
[TestClass]
public class UnitTestNomenclature {
[TestMethod]
public void ParallelSQLMethod() {
Task scropeTasks = null;
//le véritable nombre est supérieur à 1500
long[] keys = new long[] {15072000173475, 15072000173571 ... n };
try {
var tasks = keys.Select(i => Task.Run(async () => { await RunStoredProc(i); }));
scropeTasks = Task.WhenAll(tasks);
scropeTasks.Wait();
} catch (Exception ex) {
Debug.WriteLine("Exception : " + ex.Message);
Debug.WriteLine("IsFaulted : " + scropeTasks.IsFaulted);
foreach (var inx in scropeTasks.Exception.InnerExceptions) {
Debug.WriteLine("Détails : " + inx.Message);
}
}
Assert.AreEqual(1, 1);
}
public async Task RunStoredProc(long scollNumbParam) {
const string strStoredProcName = @"[dbo].[sp]";
using (SqlConnection conn = new SqlConnection(@"source de données=SERVEUR;catalogue initial=Db;sécurité intégrée=True;Trusted_Connection=Oui;")) {
await conn.OpenAsync();
Debug.WriteLine("============================================ La connexion est ouverte : ==============================================");
// info
Debug.WriteLine(String.Format("Connexion : {0}", conn.ClientConnectionId));
Debug.WriteLine(String.Format("État : {0}", conn.State.ToString()));
using (SqlCommand cmd = new SqlCommand(strStoredProcName, conn) { CommandTimeout = 120, CommandType = CommandType.StoredProcedure }) {
SqlParameter scrParam = new SqlParameter() {
ParameterName = "@KEYKRT",
Value = scollNumbParam,
SqlDbType = SqlDbType.BigInt
};
cmd.Parameters.Add(scrParam);
Debug.WriteLine("Début du traitement : " + scollNumbParam);
await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
Debug.WriteLine("Fin du traitement : " + scollNumbParam);
}
}
Debug.WriteLine("============================================ La connexion est fermée : ==============================================");
}
}
Voici ce que j'obtiens dans la fenêtre de sortie :
========== La connexion est ouverte : ========
Connexion : 5be9c681-6eb5-422f-a22c-b49689a2d912
État : Ouvert
Début du traitement : 15072000173475
========== La connexion est ouverte : ==========
Connexion : cfb66041-6646-4b56-be1c-2afb26a18cb8
État : Ouvert
Début du traitement : 15072000173571
.....
Fin du traitement : 15072000173475
=========== La connexion est fermée : =========
Fin du traitement : 15072000173571
=========== La connexion est fermée : =========
....
Un délai d'attente s'est produit en attendant des ressources de mémoire pour exécuter la requête dans le groupe de ressources 'par défaut' (2). Relancez la requête.
Numéro d'erreur réel : 8645
Numéro de ligne réel : 98
Le débogage indique également que le pool de connexions déborde Je pense que la principale raison est que la connexion n'est pas correctement libérée, mais comment puis-je y parvenir avec async ?
Si j'essaie simplement d'ouvrir une connexion avant la déclaration des tâches asynchrones et de la passer à ma méthode RunStoredProc, alors j'obtiens la connexion ne prend pas en charge MultipleActiveResultSets
using (SqlConnection conn = new SqlConnection(@"source de données=SERVEUR;catalogue initial=Db;sécurité intégrée=True;Trusted_Connection=Oui;)) {
conn.OpenAsync();
var tasks = keys.Select(i => Task.Run(async () => { await RunStoredProc(i, conn); }));
scropeTasks = Task.WhenAll(tasks);
scropeTasks.Wait();
}
Debug.WriteLine("========== La connexion est fermée : ==========");
Voici ce que j'obtiens dans la fenêtre de sortie :
Connexion : 5be9c681-6eb5-422f-a22c-b49689a2d912
État : Ouvert
Début du traitement : 15072000173475
======= La connexion est ouverte : =============
Connexion : cfb66041-6646-4b56-be1c-2afb26a18cb8
État : Ouvert
Début du traitement : 15072000173571
========= La connexion est ouverte : =========