Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use async and await in LINQ?

I'm new to ASP.NET and was trying to work on a sample project. I know this is a silly qs but please bear with me. My code below is returning only one result even when there are multiple rows returned in the SQL query. I realize that FirstOrDefaultAsync returns only the first element. I was going through the documentation here: https://msdn.microsoft.com/en-us/library/system.data.entity.queryableextensions(v=vs.113).aspx but I couldn't find what to use instead of FirstOrDefaultAsync that would return not just the first row but everything that matches my SQL condition.

This is my code so far:

    [ResponseType(typeof(Region))]
    public async Task<IHttpActionResult> GetRegion(int id)
    {

        var region_id = from sr in db.ServiceToRegions
                           where sr.Service_ID == id
                           select sr.Region_ID;

        var region = await db.Regions.Select(r =>
            new 
            {
                Region_ID = r.Region_ID,
                Region_Name = r.Region_Name
            }).FirstOrDefaultAsync(r => region_id.Contains(r.Region_ID)); //QQQ

        if (region == null)
        {
            return NotFound();
        }

        return Ok(region);
    }

What should I be using instead of FirstOrDefaultAsync?

like image 598
90abyss Avatar asked Jul 10 '16 00:07

90abyss


People also ask

Is Linq asynchronous?

Note that there are no async versions of some LINQ operators such as Where or OrderBy, because these only build up the LINQ expression tree and don't cause the query to be executed in the database. Only operators which cause query execution have async counterparts.

Should I use async with EF core?

Generally speaking, if there are asynchronous APIs, then you should use them for new code. Asynchronous code frees up the calling thread. If your application is a GUI application, this can free up the UI thread; if your application is a server application, this can free up threads to handle other requests.

What is the use of async and await in C#?

The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.

Is Select asynchronous?

I/O multiplexing—select() Like asynchronous I/O, the select() API creates a common point to wait for multiple conditions at the same time. However, select() allows an application to specify sets of descriptors to see if the following conditions exist: There is data to be read. Data can be written.


2 Answers

You should use ToListAsync() after Where:

var region = await db.Regions
    .Select(r =>
        new Region
        {
            Region_ID = r.Region_ID,
            Region_Name = r.Region_Name
        }
    )
    .Where(r => region_id.Contains(r.Region_ID))
    .ToListAsync();

https://msdn.microsoft.com/en-us/library/dn220257(v=vs.113).aspx

Note "new Region" to solve your anonymous type problem for serialization (I cannot comment on Scott's answer).

UDPATE

Because you try to partially load a model (only 2 properties), you need to use a ViewModel like this:

public class RegionVM
{
    public int Region_ID { get; set; }
    public string Region_Name { get; set; }
}

Then change your code for this:

var region = await db.Regions
    .Select(r =>
        new RegionVM
        {
            Region_ID = r.Region_ID,
            Region_Name = r.Region_Name
        }
    )
    .Where(r => region_id.Contains(r.Region_ID))
    .ToListAsync();

Don't forget to update your response type!

like image 81
Sproulx Avatar answered Oct 19 '22 20:10

Sproulx


You could replace the FirstOrDefaultAsync with a combination of a Where and a ToListAsync()

var region = await db.Regions.Select(r =>
        new 
        {
            Region_ID = r.Region_ID,
            Region_Name = r.Region_Name
        }).Where(r => region_id.Contains(r.Region_ID)).ToListAsync();

This will return a List<someAnnonamousType>.

like image 30
Scott Chamberlain Avatar answered Oct 19 '22 22:10

Scott Chamberlain