2

I'm building an API that will do paging and sorting by querying a database that as a lot of entries and I stopped at a point where I'm build methods overloading and could to put that to work well, at least at the proper way I think.

This is a mock up code:

    public virtual IAsyncEnumerable<PagedResults<T>> GetPagedItems(int i) 
    {
        return GetPagedItems(null, i);
    }

    public virtual async IAsyncEnumerable<PagedResults<T>> GetPagedItems(string s, int i) 
    {
        //here I get 2 datasets, one with the items (25 for instance)
        //and in the 2nd one I get the total count
        var datasets = await GetItemsFromDB<T>();

        var items = datasets[0].ToList();
        var totalCount = datasets[1].ReadFirst();

       yield return new PagedResults<T>
        {
            Items = items,
            TotalCount = totalCount
        };

    }

My questions is this, in the first method (the one only one parameter) it works but without the 'async' keyword.

In a first implementation I added the async and but I got a warning from visual studio saying that I cannot return a value from an iterator (makes sense), then a added the 'yield async' and it complained that I cannot convert PagedResults to an IAsyncEnumerable<PagedResults>.

I'm wondering if my final implementation it's correct and if it would work on doing the asynchronous streaming if I use the first method.

Coastpear
  • 374
  • 2
  • 15
  • Not sure why you need here `IAsyncEnumerable` in this code, cause there is no async enumeration happening, you await one time and enumerate the results, `Task>>` should be fine in this concrete case. – Guru Stron Jul 03 '20 at 14:41
  • 2
    There's nothing wrong with your code. You only need to flag a method as `async` if you use the `await` keyword within it. – Sean Jul 03 '20 at 14:41
  • If your actual code has multiple `await`'s between yield returning results, then everything should be working as expected, doing the asynchronous streaming. – Guru Stron Jul 03 '20 at 14:43
  • `async` is a compiler trick. If you have an `async` method, there's always a (often more complicated) way to write the same method, including the same return type, without `async`. This is true because *that's what the compiler does for you*. – Damien_The_Unbeliever Jul 03 '20 at 15:50
  • Why the return value is `IAsyncEnumerable>`? If you have only one `PagedResults` to yield, then a `Task>` would do the same job, while being easier to consume. – Theodor Zoulias Jul 03 '20 at 19:06
  • @theodor correct! What I could do is something like receive the values and then yield each one, not the whole thing – Coastpear Jul 04 '20 at 11:06
  • Yeap, if the consumer can do something with each individual value, then returning an `IAsyncEnumerable` makes sense. Otherwise, if the consumer buffers the values it receives because they are not useful individually, then returning a Task is simpler and more efficient. – Theodor Zoulias Jul 04 '20 at 13:52
  • @coastpear the whole point of IAsyncEnumerable I think is so we dont have to .ToList() on a dataset/IEnumerable/collection. Instead you simply return the IEnumerable and let ASP.NET do its magic to asynchronously stream the results using yield return. – BRBdot Feb 21 '23 at 05:16

0 Answers0