Как использовать функцию в где с ToListAsync () - PullRequest
0 голосов
/ 07 января 2019

Я написал функцию where, чтобы проверить, есть ли у продукта некоторая функциональность, и найти продукт с максимальной ценой.

Мои просто модели выглядят так:

 public class Product
 {
    public long ProductID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    public List<Functionality> Functionalities { get; set; }
    public List<Price> Prices { get; set; }
 }

 public class Functionality
 {
    public long FunctionalityID { get; set; }
    [MaxLength(150)]
    public string Name { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }

 public class Price
 {
    public long PriceID { get; set; }
    public decimal Value { get; set; }

    [Required]
    public long ProductID { get; set; }
    public Product Product { get; set; }
 }

тогда моя функция синхронизации, чтобы найти правильный продукт, выглядит так:

 public List<Product> GetList(ProductFiltersDto filters)
 {
    return _context.Product
        .Include(x => x.Functionality)
        .Include(x => x.Price)
        .Where(x =>
            CheckCollectionFilter(x.Functionality.Select(f => f.FunctionalityID), filters.Functionalities) &&
            CheckMaximumPrice(x.Prices , filters.MaxPrice)
         )
         .ToList();

 }

ниже моей функции где:

private bool CheckCollectionFilter<T>(IEnumerable<T> collection, List<T> filterCollection)
{
    if (filterCollection != null)
    {
        var result = true;
        foreach (var filterValue in filterCollection)
        {
            if (!collection.Contains(filterValue))
            {
                result = false;
                break;
            }
        }

        return result;
     }
     else
     {
         return true;
     }
}

private bool CheckMaximumPrice(List<Price> prices, decimal? avalibleMinPrice)
{
    return avalibleMinPrice.HasValue && prices.Count > 0 ? prices.Min(x => x.Value) <= avalibleMinPrice : true;
}

Для приведенного выше кода все работает нормально. Но когда я изменяю ToList() на ToListAsync(), я получаю ошибку

Выражение типа 'System.Collections.Generic.IAsyncEnumerable 1[System.Int64]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable 1 [System.Int64]' метода 'Boolean CheckCollectionFilter [Int64] (System.Collections.Generic.IEnumerable 1[System.Int64], System.Collections.Generic.List 1 [System.Int64])' Имя параметра: arg0

Я пробую несколько вещей, чтобы изменить IEnumerable на IAsyncEnumerable и изменить мою функцию для работы с асинхронной версией, но все же я получаю ошибку (я не нахожу способ изменить List<long> на IAsyncEnumerable<long> в предложении where).

Я читал, что функции EF Core Async имеют некоторые ограничения, но, возможно, кто-то знает, можно ли этого достичь, или пока я должен оставить это и придерживаться решения для синхронизации?

1 Ответ

0 голосов
/ 08 января 2019

Как только вы перейдете от IQueriable<T> к IEnumerable<T>, EntityFramework выполнит запрос на сервере базы данных, вытягивая все эти данные в память, и выполнит остальную часть запроса в памяти.

Если вы хотите, чтобы он работал на сервере базы данных, вы должны оставить запрос IQueriable<T> и использовать деревья выражений вместо исполняемого кода.

Вам нужно будет придумать что-то вроде этого:

private Expression<Func<T, bool>> CheckCollectionFilter<T>(IEnumerable<T> filterCollection);

private Expression<Func<T, bool>> CheckMaximumPrice<T>(decimal? avalibleMinPrice);

и измените ваш запрос на:

_context.Product
    .Include(x => x.Functionality)
    .Include(x => x.Price)
    .Where(CheckCollectionFilter(filters.Functionalities))
    .Where(CheckMaximumPrice(filters.MaxPrice))
...