Question
How to get an object from an asynchronous method?
Description
I am trying to do a similar project.
Link to the project - Link // github.com ;
Â
I try to repeat the method - 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;
}
I want to make a similar asynchronous method with an arbitrary request.
A query for example: query = query.Where (p => p.ContactName.Contains (" Maria "));
.
 Â
I try to make a simple method:
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;
}
Â
The result in the string query = query.Where (p => p.ContactName.Contains (" Maria "));
see picture.
Â
Question.
How to make such a method asynchronous with the same or different request?
Attempt number - 1. Result - does not work.
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;
        }
According to the materials of the answer: Martin. link
I am using the method.
 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;
}
I get an error:
"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).
Added by using Microsoft.EntityFrameworkCore;
.
Now the class namespace has the form:
using DBRepository.Interfaces;
using Models;
using System;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.EntityFrameworkCore;
Error (see Update-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).
has disappeared.
Description.
I am running debugging.
I get into the string var results = await query.ToListAsync ();
(of classICustomerRepositoryAnsw.GetCustomersTask1 ()
);
I press F11.
I get into the string string result =" ";
(of the class TestAnsw
method GetCustomersTask_Test()
(this method calls ICustomerRepositoryAnsw.GetCustomersTask1()
).
Result: debugging does not execute the string result = results.FirstOrDefault ();
and return result;
Question.
1. Why are the lines result = results.FirstOrDefault ();
and return result;
not executed?
There is good documentation on template the async/await
- here(I already wrote in the comment above).
 As a summary, I can say:
 Task <T>
or async
NOT makes the method asynchronous.
Only the await
keyword makes the method asynchronous.
So if you want your method to be run non-blocking you must use asynchronous API/Framework calls to the 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);
}
Looks asynchronous but is not.
But if you use the extensions method .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;
}
Now you can call this implementation via:
var customer = await YourClass.GetCustomerAsync();