Цикл Foreach асинхронный-ожидание - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть вопрос о хорошей практике использования async-await в цикле foreach.

Мой метод выглядит следующим образом

 public async Task<List<Category>> GetCategoriesAsync(string partOfName,
        CancellationToken ct = default(CancellationToken))
    {
        string lowerCasePartOfName = partOfName.ToLower();

        var categories = await _context.ECATEGORIES
            .Where(a => a.NAME.ToLower().Contains(lowerCasePartOfName))
            .ProjectTo<Category>()
            .ToListAsync(ct);

        //version1 #Beginning 
        var i = 0;
        foreach (var parentId in categories)
        {
            var categoryParent = await _context.ECATEGORIES
                .Where(a => a.ID == parentId.ParentId)
                .Select(s => s.NAME)
                .FirstOrDefaultAsync(ct);

            categories[i].CategoryParent = categoryParent;
            i++;
        }
        //version1 #End

        //version2 #Beginning 
        categories.ForEach(async x => x.CategoryParent = await _context.ECATEGORIES
            .Where(a => a.ID == x.ParentId)
            .Select(s => s.NAME).FirstOrDefaultAsync(ct));
        //version2 #End

        return categories;
    }

Version1 и version2 дают одинаковый результат, но я хотел бы спроситьчто лучше для асинхронных задач или, возможно, ни одного из них.

Заранее спасибо.

1 Ответ

0 голосов
/ 21 ноября 2018

Оба плохи в том, что код можно переписать, чтобы использовать правильное соединение.Это сделало бы вызов 1 дБ вместо 1 вызова на категорию + 1 (для первоначального вызова).Но строго отвечая на ваш вопрос, это не имеет значения: выберите тот, который вам удобнее всего с

Проблема, с которой я столкнулся, заключается в том, что parentId часто дублируется, и я не могу использовать. Содержит

Вы можете использовать левое соединение, чтобы сделать то же самое, но все в одном вызове БД, что дешевле, чем 1 вызов на результат.

string lowerCasePartOfName = partOfName.ToLower();

var categories = await (from category in _context.ECATEGORIES.Where(a => a.NAME.ToLower().Contains(lowerCasePartOfName))
    from parent in _context.ECATEGORIES.Where(parent => parent.ID == category.ParentId).DefaultIfEmpty()
    select new Category
    {
        Id = category.ID,
        CategoryParent = parent.NAME,
    }).ToListAsync();

Если ваша схема настроена без учета регистра, тоВы также можете опустить вызовы ToLower.Вы можете проверить это, посмотрев на COLLATION.

.Where(a => a.NAME.Contains(lowerCasePartOfName))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...