Как сделать асинхронный запрос без перечисления данных? - PullRequest
1 голос
/ 15 апреля 2019

Я пытаюсь понять, как написать общий метод асинхронной базы данных GetAll<T> в Entity Framework Core, не перечисляя данные.Я хочу, чтобы GetAll<T> был асинхронным, но не хочу, чтобы он перечислял данные, чтобы впоследствии я мог добавить метод Where и применить его к запросу к базе данных ..

List<Customer> customers = await _customerRepository.GetAll()
  .Where(c => c.Name.StartsWith("a"))
  .ToList();

В статье MSDN по асинхронным запросам показано следующее ...

public async Task<List<Blog>> GetBlogsAsync()
{
    using (var context = new BloggingContext())
    {
        return await context.Blogs.ToListAsync();
    }
}

... но (если я правильно понимаю) вызов ToListAsync() будет перечислять данные, что означаетон загрузит весь набор данных Blogs в память, и только после этого применяет любую фильтрацию, которую будет указывать метод Where, применяемый к результату.

Могу ли я иметь асинхронный метод, который возвращает IEnumerable<T>вместо этого?

Я очень рад не использовать репозиторий, если это лучший способ сделать это. Эта статья предполагает, что EF Core не извлекает выгоду из репозиториев, но я также не вижу, как делать то, что я хочу, его путь.

Обновление : впоясните (спасибо DavidG), идея заключается в том, что мои контроллеры ASP.NET Core могут иметь встроенный репозиторий и выполнять асинхронный запрос для получения данных.Я думал о том, чтобы сделать репозиторий универсальным и выполнить фильтрацию в контроллере, поэтому возник вопрос.Я знаю, что могу написать CustomersRepository и иметь метод CustomersThatStartWith, но тогда хранилище будет раздутым.Я искал настолько же простой репозиторий, насколько это возможно.

1 Ответ

3 голосов
/ 15 апреля 2019

Самое безопасное, что нужно сделать, это позволить вашему абоненту (в вашем случае контроллеру, хотя я бы порекомендовал оставить вашу логику вне их) передавать свои собственные фильтры. Примерно так, например:

public async Task<List<T>> GetAsync<T>(params Expression<Func<T, bool>>[] filters)
{
    IQueryable<T> query = _context.Set<T>();    

    if(filters != null)
    {
        foreach (var filter in filters)
        {
            query = query.Where(filter);
        }
    }

    return await query.ToListAsync();
}

И назовите это так:

var allUsers = await repository.GetAsync<User>();

var zombies = await repository.GetAsync<User>(u => u.IsUndead == true);

var zombieDevelopers = await repository.GetAsync<User>(
    u => u.IsUndead = true,
    u => u.JobTitle = "Developer");
...