Entity Framework SaveChanges() vs SaveChangesAsync() et Find() vs FindAsync()
J'ai été chercher les différences entre les 2 paires ci-dessus, mais n'ai pas trouvé d'articles expliquant clairement à ce sujet ainsi que lors de l'utilisation de l'un ou de l'autre.
Quelle est donc la différence entre SaveChanges()
et SaveChangesAsync()
?
Et entre Find()
et FindAsync()
?
Sur le côté serveur, lorsque nous utilisons Async
méthodes, nous avons aussi besoin d'ajouter await
. Donc, je ne pense pas que c'est asynchrone sur le côté serveur.
T-il seulement aider à prévenir l'INTERFACE utilisateur de blocage sur le côté client de navigateur? Ou il y a des avantages et des inconvénients entre eux?
- async est beaucoup, beaucoup plus que l'arrêt de la client thread de l'INTERFACE utilisateur de blocage dans les applications clientes. Je suis sûr qu'il ya une réponse d'un spécialiste à venir sous peu.
Vous devez vous connecter pour publier un commentaire.
Tout le temps que vous avez besoin pour faire une action sur un serveur distant, le programme génère la demande, l'envoie, puis attend une réponse. Je vais utiliser
SaveChanges()
etSaveChangesAsync()
comme un exemple, mais le même s'applique àFind()
etFindAsync()
.Dire que vous avez une liste
myList
de+ de 100 articles que vous devez ajouter à votre base de données. Pour insérer le, votre fonction ressemblerait à quelque chose comme ceci:D'abord, vous créez une instance de
MyEDM
, ajouter la listemyList
à la tableMyTable
, puis d'appelerSaveChanges()
pour conserver les modifications apportées à la base de données. Il fonctionne comme vous le souhaitez, les enregistrements s'engager, mais votre programme ne peut rien faire d'autre jusqu'à la validation de finitions. Cela peut prendre un certain temps en fonction de ce que vous livrez. Si vous commettez des modifications aux enregistrements, l'entité doit s'engager à ceux que l'on à la fois (une fois, j'ai eu un enregistrement de prendre 2 minutes pour les mises à jour)!Pour résoudre ce problème, vous pouvez faire une des deux choses. Le premier est que vous pouvez démarrer un nouveau thread pour gérer l'insertion. Tout cela permettra de libérer le thread appelant à poursuivre l'exécution, vous avez créé un nouveau thread qui va tout simplement s'asseoir et à attendre. Il n'est pas nécessaire pour que les frais généraux, et c'est ce que le
async await
modèle résout.Pour les I/O opperations,
await
devient rapidement votre meilleur ami. La prise de la section de code à partir de ci-dessus, nous pouvons le modifier:C'est un très petit changement, mais il y a de profonds effets sur l'efficacité et les performances de votre code. Donc ce qui se passe? Le début du code est le même, vous créez une instance de
MyEDM
et ajouter votremyList
àMyTable
. Mais lorsque vous appelezawait context.SaveChangesAsync()
, l'exécution de code renvoie à la fonction d'appel! ainsi, Alors que vous êtes en attente pour tous les enregistrements de la commettre, votre code peut continuer à exécuter. Dire la fonction qui contient le code ci-dessus a eu la signature depublic async Task SaveRecords(List<MyTable> saveList)
, la fonction d'appel pourrait ressembler à ceci:Pourquoi vous aurait une fonction de ce genre, je ne sais pas, mais ce qu'il sorties montre comment
async await
œuvres. D'abord, revenons sur ce qui se passe.L'exécution saisit
MyCallingFunction
,Function Starting
puisSave Starting
est écrit sur la console, alors la fonctionSaveChangesAsync()
est appelée. À ce stade, l'exécution renvoie àMyCallingFunction
et entre dans la boucle de l'écriture de Continuer à Exécuter' jusqu'à 1000 fois. LorsqueSaveChangesAsync()
terminée, l'exécution renvoie à laSaveRecords
fonction, écritSave Complete
à la console. Une fois que tout dansSaveRecords
terminée, l'exécution se poursuivra enMyCallingFunction
droite ou elle était quandSaveChangesAsync()
fini. Confus? Voici un exemple de sortie:Ou peut-être:
C'est la beauté de
async await
, votre code peut continuer à s'exécuter pendant que vous êtes en attente de quelque chose à la fin. En réalité, vous avez une fonction plus comme ce que votre appel de la fonction:Ici, vous avez quatre différents enregistrer l'enregistrement fonctions de passe en même temps.
MyCallingFunction
va terminer beaucoup plus rapidement en utilisantasync await
que si la personneSaveRecords
fonctions ont été appelés dans la série.La seule chose que je n'ai pas touché sur encore est le
await
mot-clé. Ce qu'il fait est d'arrêter la fonction en cours d'exécution jusqu'à ce queTask
que vous êtes en attente est terminée. Ainsi, dans le cas de l'originalMyCallingFunction
, la ligneFunction Complete
ne sera pas écrit dans la console jusqu'à ce que leSaveRecords
fonction se termine.Longue histoire courte, si vous avez une option pour utiliser
async await
, vous devriez comme il va augmenter considérablement les performances de votre application.await
cependant, même si VOUS n'avez pas besoin de faire autre chose après l'appel à SaveChanges, ASP dire "aha, ce thread est retourné en attente d'une opération asynchrone, ce qui signifie que je peux laisser ce fil gérer une autre requête du temps!" Cela permet à votre application à l'échelle horizontalement beaucoup mieux.await
pourSaveChangesAsync
depuis EF ne prend pas en charge des sauvegardes multiples en même temps. docs.microsoft.com/en-us/ef/core/saving/async Aussi, il y a en fait un grand avantage sur l'utilisation de ces méthodes asynchrones. Par exemple, vous pouvez continuer à recevoir d'autres demandes dans votre webApi lors de l'enregistrement des données ou de faire beaucoup de sutuff, ou d'améliorer l'expérience utilisateur de ne pas le gel de l'interface lorsque vous êtes dans une application de bureau.Cette affirmation est inexacte:
Vous n'avez pas besoin d'ajouter "en attente". "en attente" est simplement un moyen pratique de mot-clé en C# qui permet d'écrire des lignes de code après l'appel, et les autres lignes ne sont exécutées après l'opération de sauvegarde est terminée. Mais comme vous l'avez souligné, que vous pourriez accomplir que simplement en appelant SaveChanges au lieu de SaveChangesAsync.
Mais fondamentalement, un appel asynchrone est bien plus que cela. L'idée ici est que si il y est l'autre travail que vous pouvez le faire (sur le serveur), alors que l'opération de sauvegarde est en cours, alors vous devriez utiliser SaveChangesAsync. N'utilisez pas "en attente". Appelez simplement SaveChangesAsync, et puis continuer à faire d'autres choses en parallèle. Cela inclut potentiellement, dans une application web, qui renvoie une réponse au client, même avant l'enregistrement est terminé. Mais bien sûr, vous voulez vérifier le résultat final de la procédure d'enregistrement de sorte qu'en cas d'échec, vous pouvez le communiquer à votre utilisateur, ou journal en quelque sorte.
Mon restant d'explication sera basée sur l'extrait de code suivant.
Cas 1
Remarques: Comme la partie synchrone (vert) de
JobAsync
tours de plus que la tâchet
(rouge) ensuite, la tâchet
est déjà achevé au moment de l'await t
. En conséquence, la poursuite (bleu) fonctionne sur le même thread que le vert.La machine synchrone partie de
Main
(blanc) va tourner après que le vert est fini de tourner. C'est pourquoi la partie synchrone asynchrone de la méthode est problématique.Cas 2
Remarques: Cette affaire est à l'opposé de la première affaire. La partie synchrone (vert) de
JobAsync
rotations plus courtes que la tâchet
(rouge) ensuite, la tâchet
n'a pas été achevé au moment de l'await t
. En conséquence, la poursuite (bleu) s'exécute sur l'autre thread que le vert.La machine synchrone partie de
Main
(blanc) encore tours après le vert est fini de tourner.Cas 3
Remarques: Cette affaire permettra de résoudre le problème dans les cas précédents, à propos de la partie synchrone asynchrone de la méthode. La tâche
t
est immédiatement attendu. En conséquence, la poursuite (bleu) s'exécute sur l'autre thread que le vert.La machine synchrone partie de
Main
(blanc) va tourner immédiatement parallèle àJobAsync
.Si vous souhaitez ajouter d'autres cas, n'hésitez pas à modifier.