Entity Framework 6.1.0 SaveChangesAsync

J’ai une classe d’assistance EF qui enregistre les modifications de manière asynchrone:

public async Task SaveOrUpdateAsync(TEntity entity) where TEntity : class, IContextEntity { if (entity.Id == 0) context.Set().Add(entity); else { TEntity dbEntry = context.Set().Find(entity.Id); if (dbEntry != null) dbEntry = entity; } return await context.SaveChangesAsync(); } public void Save() { Task saveEntit1Async = repository.SaveOrUpdateAsync(entity1); Task saveEntity2Async = repository.SaveOrUpdateAsync(entity2); Task saveEntity3Async = repository.SaveOrUpdateAsync(Entity3); Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); ssortingng test = "test"; ) 

L’appel est bloqué

 Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); 

ligne et n’arrive jamais à

  ssortingng test = "test"; 

Mais si je le lance comme:

 public void Save() { repository.SaveOrUpdateAsync(entity1); repository.SaveOrUpdateAsync(entity2); repository.SaveOrUpdateAsync(Entity3); ssortingng test = "test"; ) 

Cela fonctionne bien, tous les changements sont en cours de sauvegarde et il arrive à

 ssortingng test = "test"; 

Pourquoi est-ce

 Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); 

Gèle l’opération et ne passe jamais l’appel à la ligne de code suivante (ssortingng test = “test”;)?

Je l’ai compris!

Voici le problème qui se produisait lorsque, lorsque vous attendez la tâche avec la méthode “Wait” ou que vous prenez le résultat directement à partir de la propriété “Résultat” de la tâche, vous bloquez le thread principal en même temps. Lorsque la tâche finit par se terminer dans cette méthode (SaveOrUpdateAsync (entité TEntity)) dans le pool de threads, elle appelle la suite pour la publier dans le thread principal (car elle ne l’a jamais laissée), car SynchronizationContext.Current est disponible et capturé . Mais voici un problème: le thread principal est bloqué par la méthode “Wait” et c’est ainsi que je me trouvais dans une impasse!

Pour résoudre le problème de blocage, je devais spécifier de ne pas continuer sur le contexte capturé pour context.SaveChangesAsync ().

 public async Task SaveOrUpdateAsync(TEntity entity) where TEntity : class, IContextEntity { if (entity.Id == 0) context.Set().Add(entity); else { TEntity dbEntry = context.Set().Find(entity.Id); if (dbEntry != null) dbEntry = entity; } return await context.SaveChangesAsync().ConfigureAwait(continueOnCapturedContext: false); } 

peut-être que je suis stupide (!), mais pourquoi votre code dit

 if (dbEntry != null) dbEntry = entity; 

sûrement que si la déclaration devrait être

 if (dbEntry == null) dbEntry = entity; 

Je suppose que l’opérateur de coalescence nul en C # travaillerait également pour remplacer les deux lignes

 TEntity dbEntry = context.Set().Find(entity.Id) ?? entity;