2

Этот пример относится к сущностной структуре, но вопрос в том, как делать await несколько задач async в цикле. Скажем, у меня есть следующий метод на настраиваемой DbContext класса:Async & ждут несколько задач в цикле, как вернуть одну задачу

public async Task DiscardChangesAsync() 
{ 
    foreach (var entry in ChangeTracker.Entries().Where(x => x != null)) 
    { 
     switch (entry.State) 
     { 
      case EntityState.Added: 
       entry.State = EntityState.Detached; 
       break; 
      case EntityState.Modified: 
       entry.State = EntityState.Unchanged; 
       break; 
      case EntityState.Deleted: 
       await entry.ReloadAsync(); // <-- only async method 
       break; 
     } 
    } 
} 

Приведенные выше компилируется и работает, но я не уверен, насколько эффективно это. Например, если контекст содержит 10 удаленных записей сущностей, поток останавливается и ждет на каждом ReloadAsync, прежде чем он продолжит цикл, правильно? Есть ли способ разрешить выполнение цикла и вернуть новый Task, который не будет завершен до тех пор, пока все 10 из ReloadAsync вызовов не будут завершены?

ответ

4

Чтобы ответить на ваш вопрос строго:

public Task DiscardChangesAsync() 
{ 
    List<Task> tasks = new List<Task>(); 
    foreach (var entry in ChangeTracker.Entries().Where(x => x != null)) 
    { 
     switch (entry.State) 
     { 
      case EntityState.Added: 
       entry.State = EntityState.Detached; 
       break; 
      case EntityState.Modified: 
       entry.State = EntityState.Unchanged; 
       break; 
      case EntityState.Deleted: 
       tasks.Add(entry.ReloadAsync()); 
       break; 
     } 
    } 

    return Task.WhenAll(tasks); 
} 

Может быть более эффективным, хотя, чтобы EF ручку перезагрузки все они сразу:

public Task DiscardChangesAsync() 
{ 
    List<DbEntityEntry> deleted = new List<DbEntityEntry>(); 

    foreach (var entry in ChangeTracker.Entries().Where(x => x != null)) 
    { 
     switch (entry.State) 
     { 
      case EntityState.Added: 
       entry.State = EntityState.Detached; 
       break; 
      case EntityState.Modified: 
       entry.State = EntityState.Unchanged; 
       break; 
      case EntityState.Deleted: 
       deleted.Add(entry); 
       break; 
     } 
    } 

    return ctx.RefreshAsync(RefreshMode.StoreWins, deleted); 
} 
+0

Я бы бросить 'это 'to' IObjectContextAdapter', чтобы вызвать 'RefreshAsync'. Есть вопросы? Интересно, почему они опустили этот метод из 'DbContext' ..? Кроме того, аргумент не должен быть 'RefreshMode.StoreWins' вместо' RefreshMode.OverwriteCurrentValues'? – danludwig

+0

Оказывается, второй более эффективный вариант не работает во время выполнения. После извлечения 'DbContext' в' IObjectContextAdapter' и использования 'RefreshMode.StoreWins' для его компиляции мой интеграционный тест завершился неудачей:« Элемент с индексом 0 в коллекции объектов для обновления имеет значение null EntityKey или имеет значение не привязанный к этому объектуStateManager. " Первый строгий ответ, тем не менее, не проваливает интеграционный тест. – danludwig

+0

Ahh, я дал вам LINQ to SQL 'RefreshMode'. Вы правы, 'RefreshMode.StoreWins' является правильным. –

Смежные вопросы