Question

I'm using EF6 and want to make the following query fully asynchronous:

 await MyDataContext.ADbSet.
                     First(a => a.Something == "Something").
                     ASubCollection.
                     Select(x => new { x.SubCollectionId }).
                     ToListAsync();

This doesn't work, I believe due to First() returning the actual entity and access to ASubCollection being an ICollection, not an IQueryable.

I was able to work around this with the following code:

 await MyDataContext.ADbSet.
                     Where(a => a.Something == "Something").
                     SelectMany(a => a.ASubCollection).
                     Select(x => new { x.SubCollectionId }).
                     ToListAsync();

However, this seems "hacky" as I'm using a Where(...) when I should be using a First() as I know at compile time that there will be exactly one element satisfying the query. Is there a better way of doing this?

Was it helpful?

Solution

The call to First() is a call that actually enumerates the underlying sequence and returns an entity instead of a Task. Thus First() won't work together with the await-keyword.

Your second solution is completely valid (and not "hacky" at all) in this context, because there is no need to add a limit to the generated database query, as the Where(...)-call will return exactly one element in this special case - with or without a limit in the query.

If the Where-call is likely to return multiple elements, or you simply want to ensure that there will be only the first element considered, inserting a call to Take(1) will bring the first element of the sequence, but still be an IQueryable:

await MyDataContext.ADbSet
                   .Where(a => a.Something == "Something")
                   .Take(1)
                   .SelectMany(a => a.ASubCollection)
                   .Select(x => new { x.SubCollectionId })
                   .ToListAsync();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top