Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use IAsyncEnumerable in repository class

I am creating a small API using .net core 3.1 with EF core.
And I am trying to use IAsyncEnumerable in my repository class but I am getting error.
Error is valid I know but can anybody tell me how to use IAsyncEnumerable in repository class ?

StateRepository.cs

    public class StateRepository : IStateRepository
    {
        public StateRepository(AssetDbContext dbContext)
            : base(dbContext)
        {

        }

        public async Task<State> GetStateByIdAsync(Guid id)
            => await _dbContext.States
                .Include(s => s.Country)
                .FirstOrDefaultAsync(s => s.StateId == id);

        public async IAsyncEnumerable<State> GetStates()
        {
            // Error says:
            //cannot return a value from iterator. 
            //Use the yield return statement to return a value, or yield break to end the iteration
             return await _dbContext.States
                       .Include(s => s.Country)
                       .ToListAsync();
        }
    }

Can anybody tell me where I am going wrong ?
Thanks

like image 212
Shaksham Singh Avatar asked Dec 31 '22 00:12

Shaksham Singh


1 Answers

IAsyncEnumerable is not what you think it is.

IAsyncEnumerable is used within an async method that uses the "yield" keyword. IAsyncEnumerbale allows it to return each item one by one. For example if you were working on something that was IOT and you wanted to "stream" results as they came in.

static async IAsyncEnumerable<int> FetchIOTData()
{
    for (int i = 1; i <= 10; i++)
    {
        await Task.Delay(1000);//Simulate waiting for data to come through. 
        yield return i;
    }
}

If you are interested more in IAsyncEnumerable you can read more here : https://dotnetcoretutorials.com/2019/01/09/iasyncenumerable-in-c-8/

In your case, you are not using Yield because you have the entire list from the get go. You just need to use a regular old Task. For example :

public async Task<IEnumerable<<State>> GetStates()
{
    // Error says:
    //cannot return a value from iterator. 
    //Use the yield return statement to return a value, or yield break to end the iteration
     return await _dbContext.States
               .Include(s => s.Country)
               .ToListAsync();
}

If you were calling some service that returned States one by one and you wanted to read those States one by one, then you would use IAsyncEnumerable. But with your given example (And frankly, most use cases), you will be fine just using Task

like image 109
MindingData Avatar answered Jan 12 '23 09:01

MindingData