Entity Framework SaveChanges () vs SaveChangesAsync () et Find () vs FindAsync ()

J’ai cherché les différences entre 2 paires ci-dessus, mais je n’ai trouvé aucun article expliquant clairement à ce sujet, ni quand utiliser l’un ou l’autre.

Alors, quelle est la différence entre SaveChanges() et SaveChangesAsync() ?
Et entre Find() et FindAsync() ?

Côté serveur, lorsque nous utilisons des méthodes Async , nous devons également append Ainsi, je ne pense pas que ce soit asynchrone côté serveur.

Cela vous aide-t-il uniquement à empêcher le blocage de l’interface utilisateur sur le navigateur côté client? Ou y at-il des avantages et des inconvénients entre eux?

Chaque fois que vous devez effectuer une action sur un serveur distant, votre programme génère la demande, l’envoie, puis attend une réponse. Je vais utiliser SaveChanges() et SaveChangesAsync() comme exemple, mais il en va de même pour Find() et FindAsync() .

Disons que vous avez une liste myList de plus de 100 éléments que vous devez append à votre firebase database. Pour insérer cela, votre fonction ressemblerait à quelque chose comme ceci:

 using(var context = new MyEDM()) { context.MyTable.AddRange(myList); context.SaveChanges(); } 

Tout d’abord, vous créez et MyEDM , ajoutez la liste myList à la table MyTable , puis appelez SaveChanges() pour conserver les modifications apscopes à la firebase database. Cela fonctionne comme vous voulez, les enregistrements sont validés, mais votre programme ne peut rien faire avant que la validation ne soit terminée. Cela peut prendre beaucoup de temps en fonction de ce que vous commettez. Si vous apportez des modifications aux enregistrements, l’entité doit les valider un par un (une fois, j’ai économisé 2 minutes pour les mises à jour)!

Pour résoudre ce problème, vous pouvez faire l’une des deux choses suivantes: Le premier est que vous pouvez démarrer un nouveau thread pour gérer l’insertion. Bien que cela libère le thread appelant pour continuer à exécuter, vous avez créé un nouveau thread qui va juste restr là et attendre. Il n’y a pas besoin de cette surcharge, et c’est ce que les async await modèle de résolution.

Pour les opérations d’E / S, await vite pour devenir votre meilleur ami. En prenant la section de code ci-dessus, nous pouvons la modifier pour être:

 using(var context = new MyEDM()) { Console.WriteLine("Save Starting"); context.MyTable.AddRange(myList); await context.SaveChangesAsync(); Console.WriteLine("Save Complete"); } 

C’est un tout petit changement, mais il y a des effets profonds sur l’efficacité et la performance de votre code. Alors que se passe-t-il? Le début du code est le même, vous créez une instance de MyEDM et ajoutez votre myList à MyTable . Mais lorsque vous appelez await context.SaveChangesAsync() , l’exécution du code retourne à la fonction appelante! Ainsi, pendant que vous attendez que tous ces enregistrements soient validés, votre code peut continuer à s’exécuter. Supposons que la fonction qui contenait le code ci-dessus avait la signature de public async Task SaveRecords(List saveList) , la fonction appelante pourrait ressembler à ceci:

 public async Task MyCallingFunction() { Console.WriteLine("Function Starting"); Task saveTask = SaveRecords(GenerateNewRecords()); for(int i = 0; i < 1000; i++){ Console.WriteLine("Continuing to execute!"); } await saveTask; Console.Log("Function Complete"); } 

Pourquoi vous auriez une fonction comme celle-ci, je ne sais pas, mais ce qu'elle affiche montre comment async await travaux. Commençons d'abord par ce qui se passe.

L'exécution entre la fonction MyCallingFunction , Function Starting moment, Save Starting est écrit sur la console, puis la fonction SaveChangesAsync() est appelée. A ce stade, l'exécution retourne à MyCallingFunction et entre dans la boucle for en écrivant «Continuing to Execute» jusqu'à 1000 fois. Lorsque SaveChangesAsync() finit, l'exécution retourne à la fonction SaveRecords écrivant Save Complete sur la console. Une fois que tout dans SaveRecords terminé, l'exécution continue dans MyCallingFunction à MyCallingFunction que SaveChangesAsync() termine. Confus? Voici un exemple de sortie:

 Fonction de démarrage
 Enregistrer à partir de
 Continuer à exécuter!
 Continuer à exécuter!
 Continuer à exécuter!
 Continuer à exécuter!
 Continuer à exécuter!
 ....
 Continuer à exécuter!
 Sauver Complete!
 Continuer à exécuter!
 Continuer à exécuter!
 Continuer à exécuter!
 ....
 Continuer à exécuter!
 Fonction complète!

Ou peut-être:

 Fonction de démarrage
 Enregistrer à partir de
 Continuer à exécuter!
 Continuer à exécuter!
 Sauver Complete!
 Continuer à exécuter!
 Continuer à exécuter!
 Continuer à exécuter!
 ....
 Continuer à exécuter!
 Fonction complète!

C'est la beauté de l' async await , votre code peut continuer à fonctionner pendant que vous attendez que quelque chose se termine. En réalité, vous auriez une fonction similaire à celle de votre fonction d'appel:

 public async Task MyCallingFunction() { List myTasks = new List(); myTasks.Add(SaveRecords(GenerateNewRecords())); myTasks.Add(SaveRecords2(GenerateNewRecords2())); myTasks.Add(SaveRecords3(GenerateNewRecords3())); myTasks.Add(SaveRecords4(GenerateNewRecords4())); await Task.WhenAll(myTasks.ToArray()); } 

Ici, vous avez quatre fonctions d'enregistrement de sauvegarde différentes en même temps . MyCallingFunction se terminera beaucoup plus rapidement en utilisant async await si les fonctions individuelles de SaveRecords ont été appelées en série.

La seule chose que je n'ai pas encore abordée est le mot-clé await . Cela empêche la fonction actuelle de s'exécuter jusqu'à ce que la Task soit terminée. Ainsi, dans le cas de la fonction MyCallingFunction origine, la ligne Function Complete ne sera pas écrite dans la console tant que la fonction SaveRecords ne sera pas terminée.

En bref, si vous avez une option pour utiliser async await , vous devriez, car cela va grandement améliorer les performances de votre application.

Cette déclaration est incorrecte:

Côté serveur, lorsque nous utilisons des méthodes Async, nous devons également append

Vous n’avez pas besoin d’append “wait”. “wait” est simplement un mot clé pratique en C # qui vous permet d’écrire plus de lignes de code après l’appel, et ces autres lignes ne seront exécutées qu’à la fin de l’opération de sauvegarde. Mais comme vous l’avez souligné, vous pouvez accomplir cela simplement en appelant SaveChanges au lieu de SaveChangesAsync.

Mais fondamentalement, un appel asynchrone est beaucoup plus que cela. L’idée ici est que si vous pouvez faire d’autres tâches (sur le serveur) pendant que l’opération de sauvegarde est en cours, vous devez utiliser SaveChangesAsync. Ne pas utiliser “attendre”. Appelez simplement SaveChangesAsync, puis continuez à faire d’autres choses en parallèle. Cela inclut potentiellement, dans une application Web, le retour d’une réponse au client avant même que la sauvegarde soit terminée. Mais bien sûr, vous voudrez toujours vérifier le résultat final de la sauvegarde afin que, en cas d’échec, vous puissiez le communiquer à votre utilisateur ou le connecter d’une manière ou d’une autre.