How to get an object from an asynchronous method?

.net-core c# entity-framework-core linq

Question

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;
        }

Picture-1
enter image description here

Picture-2
enter image description here


Update 1. ##

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).

Picture-1
enter image description here


Update 2

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?

Picture-1 enter image description here

Picture-2 enter image description here

1
0
3/28/2020 9:27:57 AM

Accepted Answer

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();

Then it will run non-blocking async.

EntityFramework Core

1
3/28/2020 6:04:36 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow