Как получить объект из асинхронного метода?

Вопрос
Как получить объект из асинхронного метода?

Описание
Я пытаюсь сделать подобный проект.
Ссылка на проект - Ссылка // github.com ;
Я пытаюсь повторить метод - GetPosts (int index, int pageSize, string tag = null) .

public async Task<Page<Post>> GetPosts(int index, int pageSize, string tag = null)
    {
        var result = new Page<Post>() { CurrentPage = index, PageSize = pageSize };

        using (var context = ContextFactory.CreateDbContext(ConnectionString))
        {
            var query = context.Posts.AsQueryable();
            if (!string.IsNullOrWhiteSpace(tag))
            {
                query = query.Where(p => p.Tags.Any(t => t.TagName == tag));
            }

            result.TotalPages = await query.CountAsync();
            result.Records = await query.Include(p => p.Tags).Include(p => p.Comments).OrderByDescending(p => p.CreatedDate).Skip(index * pageSize).Take(pageSize).ToListAsync();
        }

        return result;
    }

Я хочу сделать аналогичный асинхронный метод с произвольным запросом.
Запрос, например: query = query.Where (p => p.ContactName.Contains (" Maria ")); ,
Я пытаюсь сделать простой метод:

public Customer GetCustomers ()
{
    Customer result = new Customer ();
 
    using (var context = ContextFactory.CreateDbContext (ConnectionString))
    {
      var query = context.Customers.AsQueryable ();
      query = query.Where (p => p.ContactName.Contains ("Maria")); //
      result = query as Customer;
    }
    return result;
}


Результат в строке query = query.Where (p => p.ContactName.Contains (" Maria ")); смотри картинку.

Вопрос.
Как сделать такой метод асинхронным с тем же или другим запросом?

Число попыток - 1. Результат - не работает.

public Task <Customer> GetCustomersTask ()
        {
            // Customer result = new Customer ();
 
            var result = new TaskCompletionSource <Customer> ();
 
            using (var context = ContextFactory.CreateDbContext (ConnectionString))
            {
                Task.Run (() =>
                {
                    var query = context.Customers.AsQueryable ();
                    query = query.Where (p => p.ContactName == "Maria");
 
                    result.SetResult (query as Customer);
                }
                );
            }
            return result.Task;
        }

Picture-1
введите описание изображения здесь

Picture-2
введите описание изображения здесь


Обновление 1. ##

По материалам ответа: Мартин. ссылка на сайт

Я использую метод.

 public async Task <Customer> GetCustomerAsync ()
{
    Customer result = new Customer ();

    using (var context = ContextFactory.CreateDbContext (ConnectionString))
    {
      var query = context.Customers.AsQueryable ();
      query = query.Where (p => p.ContactName.Contains ("Maria")); //
      var results = await query.ToListAsync ();
      result = results.FirstOrDefault ();
    }
    return result;
}

Я получаю ошибку:
«IQueryable» не содержит определения «ToListAsync» и не может найти доступный метод расширения «ToListAsync», тип хоста «IQueryable» в качестве первого аргумента (возможно, с использованием директивы или ссылки на сборку отсутствует).

Picture-1
введите описание изображения здесь


Обновление 2

Добавлено с using Microsoft.EntityFrameworkCore; ,
Теперь пространство имен класса имеет вид:
using DBRepository.Interfaces;
using Models;
using System;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.EntityFrameworkCore;

Ошибка (см. Обновление-1 ):
"IQueryable" does not contain a definition of "ToListAsync", and could not find an available extension method "ToListAsync", host type "IQueryable" as the first argument (possibly using directive or assembly reference missing). исчез.

Описание.
Я бегу отладки.
Я попадаю в строку var results = await query.ToListAsync (); (класса ICustomerRepositoryAnsw.GetCustomersTask1 () );
Я нажимаю F11.
Я попадаю в строку string result =" "; (из метода GetCustomersTask_Test() класса TestAnsw GetCustomersTask_Test() (этот метод вызывает ICustomerRepositoryAnsw.GetCustomersTask1() ).
Результат: при отладке не выполняется строка result = results.FirstOrDefault (); и return result;

Вопрос.
1. Почему строки являются result = results.FirstOrDefault (); и return result; не выполнен?

Picture-1 введите описание изображения здесь

Picture-2 введите описание изображения здесь

Всего 1 ответ


Есть хорошая документация по шаблону async/await - здесь (я уже писал в комментарии выше).
В качестве резюме я могу сказать:
Task <T> или async NOT делает метод асинхронным.
Только ключевое слово await делает метод асинхронным.

Поэтому, если вы хотите, чтобы ваш метод выполнялся неблокирующим, вы должны использовать асинхронные вызовы API / Framework к EntityFramework.

public Task<Customer> GetCustomerAsync ()
{
    Customer result = new Customer ();

    using (var context = ContextFactory.CreateDbContext (ConnectionString))
    {
      var query = context.Customers.AsQueryable ();
      query = query.Where(p => p.ContactName.Contains ("Maria")); //
      result = query.FirstOrDefault();
    }
    return Task.FromResult(result);
}

Выглядит асинхронно, но это не так .

Но если вы используете метод расширений .ToListAsync()

public async Task<Customer> GetCustomerAsync ()
{
    Customer result = new Customer ();

    using (var context = ContextFactory.CreateDbContext (ConnectionString))
    {
      var query = context.Customers.AsQueryable ();
      query = query.Where (p => p.ContactName.Contains ("Maria")); //
      var results = await query.ToListAsync();
      result = results?.FirstOrDefault();
    }
    return result;
}

Теперь вы можете вызвать эту реализацию через:

var customer = await YourClass.GetCustomerAsync();

Затем будет запущена неблокирующая асинхронность.

EntityFramework Core


Есть идеи?

10000