ToDictionaryAsync retrieves the whole object from the database in Entity Framework

9/8/2025
2 minute read

In Entity Framework Core ToDictionaryAsync (and of course) also the the synchronous counter part ToDictionary retrieve the whole object from the database.

ToDictionaryAsync

If you have a look at the definition of ToDictionaryAsync:

public static Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TSource, TKey, TElement>(
    this IQueryable<TSource> source,
    Func<TSource, TKey> keySelector,
    Func<TSource, TElement> elementSelector,
    CancellationToken cancellationToken = default)
    where TKey : notnull
    => ToDictionaryAsync(source, keySelector, elementSelector, comparer: null, cancellationToken);

Then we can see it accepts a lambda over an expression aka (Expression<Func<TSource, TKey>>). That also means, that the evaluation of this is done client-side! So if you have a query and object as such:

public class BlogPost
{
    public int Id { get; set; }
    public required string Title { get; set; }
    public required string Description { get; set; }
    public required string Content { get; set; }
    public required string Author { get; set; }
}

And you do something like this:

return await dbContext.BlogPosts
    .Where(...)
    .ToDictionaryAsync(k => k.Author, v => v.Title) // Could also be useful

Then you are not only retrieving Author and Title from the database, but for example also Content. I came across this ticket that made me realise this! So to come around use Select as this is evaluated on the server-side:

return await dbContext.BlogPosts
    .Where(...)
    .Select(s => new { Author = s.Author, Title = s.Title })
    .ToDictionaryAsync(k => k.Author, v => v.Title) // Could also be useful
An error has occurred. This application may no longer respond until reloaded. Reload x