SqlConnection.Open vs SqlConnection.OpenAsync – Quelle est la différence entre les deux au-delà de l’évidence?

Edit: Cela revient à comprendre pourquoi le fait de modifier SqlConnection.Open () uniquement pour attendre SqlConnection.OpenAsync () dans le code asynchrone entraîne un comportement très différent.

Quelle est la différence entre un appel SqlConnection.Open dans un code synchrone et un appel en attente SqlConnection.OpenAsync dans un code asynchrone en dehors du comportement asynchrone évident? La connexion sous-jacente est-elle asynchrone avec la firebase database?

La documentation sur OpenAsync est légère, à l’ adresse https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.openasync%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 .

Une version asynchrone de Open, qui ouvre une connexion à une firebase database avec les parameters spécifiés par ConnectionSsortingng. Cette méthode appelle la méthode virtuelle OpenAsync with CancellationToken.None. (Hérité de DbConnection.)

Je trouve intéressant que, précédemment, la chaîne de connexion nécessitait async = true, alors que dans .net 4.5+, ce n’est plus nécessaire. Est-ce que les connexions se comportent différemment?

https://msdn.microsoft.com/en-us/library/hh211418(v=vs.110).aspx

Depuis le .NET Framework 4.5, ces méthodes ne requièrent plus de traitement asynchrone = true dans la chaîne de connexion.

Quand j’utilise par hasard le fichier synchrone SqlConnection.Open dans une application asynchrone et que je le charge fortement, je constate qu’il fonctionne très mal et que le pool de connexions est exécuté à sec au plus tôt. Je m’attendais à ce que l’ouverture de la connexion bloque, cependant, l’exécution de commandes asynchrones (via Dapper) sur ces connexions se comporte différemment. Alors, qu’est-ce que OpenAsync fait différemment?

MODIFIER:

En tant que code demandé pour reproduire le problème (ou peut-être démontrer une différence). L’exécution de ce cas avec Open () entraîne des dépassements de délai de connexion lors de l’exécution d’environ 180 commandes asynchrones simultanées. Avec OpenAsync (), aucune exception n’est rencontrée, même lors de plus de 300 commandes simultanées. Vous pouvez pousser la simultanéité pour qu’elle finisse par expirer, mais elle le fait beaucoup plus profondément dans les commandes concurrentes.

using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Dapper; using Nito.AsyncEx; namespace AsyncSqlConnectionTest { class Program { public static int concurrent_counter = 0; public static int total_counter = 0; static void Main(ssortingng[] args) { var listToConsume = Enumerable.Range(1, 10000).ToList(); Parallel.ForEach(listToConsume, new ParallelOptions { }, value => { try { Task.Run(() => AsyncContext.Run(async () => { using (var conn = new SqlConnection("Data Source=.; Database=master; Trusted_Connection=True;")) { Interlocked.Increment(ref concurrent_counter); Interlocked.Increment(ref total_counter); await conn.OpenAsync(); var result = await conn.QueryAsync("select * from master..spt_values; waitfor delay '00:00:05'"); Console.WriteLine($"#{total_counter}, concurrent: {concurrent_counter}"); Interlocked.Decrement(ref concurrent_counter); } })).GetAwaiter().GetResult(); } catch (Exception e) { Console.Write(e.ToSsortingng()); } }); Console.ReadLine(); } } } 

EDIT 2:

Voici un test qui trouve les mêmes différences en n’utilisant que ADO.NET. Il convient de noter que Dapper s’exécute beaucoup plus rapidement, mais ce n’est pas le problème ici. Encore une fois, OpenAsync aura éventuellement un délai d’expiration, mais beaucoup plus tard et jamais si le degré de parallélisme maximal est de 100 (inférieur à la taille du pool de connexions).

 using System; using System.Data.SqlClient; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsyncSqlConnectionTest { class Program { public static int concurrent_counter = 0; public static int total_counter = 0; static void Main(ssortingng[] args) { var listToConsume = Enumerable.Range(1, 10000).ToList(); Parallel.ForEach(listToConsume, new ParallelOptions { }, value => { try { Task.Run(async () => { using (var conn = new SqlConnection("Data Source=.; Database=master; Trusted_Connection=True;")) { Interlocked.Increment(ref concurrent_counter); Interlocked.Increment(ref total_counter); // this (no errors) await conn.OpenAsync(); // vs. this (timeouts) //conn.Open(); var cmd = new SqlCommand("select * from master..spt_values; waitfor delay '00:00:05'", conn); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { } } Console.WriteLine($"#{total_counter}, concurrent: {concurrent_counter}"); Interlocked.Decrement(ref concurrent_counter); } }).GetAwaiter().GetResult(); } catch (Exception e) { Console.Write(e.ToSsortingng()); } }); Console.ReadLine(); } } }