简体   繁体   中英

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?

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!

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

In that case you want all records, you should remove the call to FirstOrDefaultAsync() which will return you IEnumerable<anonymoustype> like below. You can include the condition using Where() LINQ extension method

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM