Entity Framework 6.1.0 SaveChangesAsync

I have an EF helper class that saves async changes:

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

Call stuck on

 Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); 

and never gets into

  string test = "test"; 

But if I ran it like:

 public void Save() { repository.SaveOrUpdateAsync<Entity1>(entity1); repository.SaveOrUpdateAsync<Entity2>(entity2); repository.SaveOrUpdateAsync<Entity3>(Entity3); string test = "test"; ) 

It works great, all changes are saved and reach

 string test = "test"; 

Why

 Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); 

It freezes the operation and never passes the call to the next line of code (line test = "test";)?

+7
c # asynchronous entity-framework
source share
2 answers

I get it!

Here is the problem that occurs when you wait in a Task using the Wait method or accept a result directly from the Task Result property, you block the main thread at the same time. When the Task eventually completes inside this method (SaveOrUpdateAsync (TEntity object)) in the thread pool, it will trigger a continuation to send back to the main thread (since it never left it), since SynchronizationContext.Current is available and captured, But here problem: the main thread is blocked by the Wait method, and thatโ€™s how I got to a dead end!

To fix the deadlock issue, I had to specify not to continue the captured context for context.SaveChangesAsync ().

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

I may be stupid (!), But why does your code say

 if (dbEntry != null) dbEntry = entity; 

Of course, if the operator should be

 if (dbEntry == null) dbEntry = entity; 

I assume the C # null-coalescing statement will also work to replace both strings

 TEntity dbEntry = context.Set<TEntity>().Find(entity.Id) ?? entity; 
0
source share

All Articles