5

I've just realised that this code:

    public async Task<List<Review>> GetTitleReviews(int titleID)
    {
        using (var context = new exampleEntities())
        {
            return await context.Reviews.Where(x => x.Title_Id == titleID).ToList();        
        }
    }

...will not work as async methods cannot await LINQ expressions. I've did some searches but only managed to find some overcomplicated solutions.

How should functions which return LINQ expressions be converted to async versions?

3
  • 1
    You probably wanted to say LINQ extension methods, not "lambdas"? Commented Oct 30, 2014 at 1:55
  • 1
    add using System.Data.Entity and use ToListAsync() Commented Oct 30, 2014 at 1:56
  • @zerkms correct, updated Commented Oct 30, 2014 at 2:04

3 Answers 3

13

Add the System.Data.Entity namespace and take advantage of the Async extension methods

In this case ToListAsync should do the trick

using System.Data.Entity;

public async Task<List<Review>> GetTitleReviews(int titleID)
{
    using (var context = new exampleEntities())
    {
        return await context.Reviews.Where(x => x.Title_Id == titleID).ToListAsync();        
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Although both yours and Peter Duniho's answers worked, I'm marking yours as the answer since it provides a pretty much built-in Async-equivalent method of my original code.
There are many Async extension in that namespace that are very handy when working with EntityFramework, FirstOrDefaluAsync and ForEachAsync are some of my everyday uses
6

Technically, that method doesn't return a lambda. It returns a List<Review>.

It's true what you posted won't compile. But this would:

public async Task<List<Review>> GetTitleReviews(int titleID)
{
    using (var context = new exampleEntities())
    {
        return await Task.Run(() => context.Reviews.Where(x => x.Title_Id == titleID).ToList());
    }
}

If that doesn't answer your question, maybe you can be more clear about exactly what you're trying to accomplish and why the above doesn't do it.

3 Comments

I've just tried both yours and @sa_ddam213's solutions and both work, but his solution seems more straightforward. How do your solutions differ in the back-end?
The biggest difference is that the other solution requires loading EF into the process for just one method. If you already have EF referenced, it's not a bad approach. But I wouldn't want to take a dependency on EF just for that.
I should also mention: each scenario's different, but there can be other performance issues using the EF version, as compared with wrapping the entire expression in a Task. Here, we are only assured of deferred execution for the LINQ Where() method. Ideally, the Reviews property would be fast; it might be deferred execution, or precomputed. In general, we're should be able to assume that property getters are fast. But not everyone follows that rule. Using the EF method could expose the code to unwanted latency if the elements of the expression before the ToListAsync() are slow.
0

I solved this problem creating an Enumerable extension. That was needed for me because Xamarin Forms don't have Linq ToListAsync support. This is my extension:

public static class EnumerableExtension
{
    public static Task<List<T>> ToListAsync<T>(this IEnumerable<T> enumerable)
    {
        return Task.Run(enumerable.ToList);
    }
}

2 Comments

That's a neat, but also controversial idea.
For me that this problem appeared like that: that's a screen made in Xamarin Forms is making the app stop... Solve it! So, I found the same problem along all the app: synchronously LINQ operations everywhere. That lock the main thread and, consequently, make the Android close the app. Xamarin Forms don't have ToListAsync and repeat my self with Task.Run(()=>...) it's not good in a big code base. My only ways out was: to create an extension or a static method. I choose extension for the flexibility. I never even know that's a controversial ideia... Thanks to share this knowledge!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.