liveBook · Manning

ToListAsync

As explained in Pro ASP.NET Core 7, Tenth Edition

ToListAsync is an asynchronous .NET query-extension method that evaluates a query and materializes its results into a list.

ToListAsync asynchronously evaluates an Entity Framework Core query and materializes its results into a list. Assigning that list to component state lets repeated reads use existing data instead of dispatching more queries. section 36.3.2

Use ToListAsync when query timing should be explicit:

  • Run the initial query when the Blazor component initializes. section 36.3.2
  • Refresh data deliberately from an Update button by invoking a method that calls ToListAsync again. section 36.3.2
  • Apply OrderBy to IQueryable<T> before ToListAsync to send sorting to the database, or sort the materialized list without another query. section 36.3.2
Listing 36.18 Controlling queries in the List.razor file in the Blazor/Forms folder
@page "/forms"
@page "/forms/list"
@layout EmptyLayout

<h5 class="bg-primary text-white text-center p-2">People</h5>

<table class="table table-sm table-striped table-bordered">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Dept</th>
            <th>Location</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @if (People.Count() == 0) {
            <tr>
                <th colspan="5" class="p-4 text-center">
                    Loading Data...
                </th>
            </tr>
        } else {
            @foreach (Person p in People) {
                <tr>
                    <td>@p.PersonId</td>
                    <td>@p.Surname, @p.Firstname</td>
                    <td>@p.Department?.Name</td>
                    <td>@p.Location?.City</td>
                    <td>
                        <NavLink class="btn btn-sm btn-warning"
                         href="@GetEditUrl(p.PersonId)">
                            Edit
                        </NavLink>
                    </td>
                </tr>
            }
        }
    </tbody>
</table>

<button class="btn btn-danger" @onclick="UpdateData">Update</button>

<button class="btn btn-primary" @onclick="@(() => Counter++)">
    Increment
</button>
<span class="h5">Counter: @Counter</span>

@code {

    [Inject]
    public DataContext? Context { get; set; }
 
    public IEnumerable<Person> People { get; set; }
        = Enumerable.Empty<Person>();
                
    protected async override Task OnInitializedAsync() {
        await UpdateData();
    }
        
    private async Task UpdateData() {
        if (Context != null) {
            People = await Context.People.Include(p => p.Department)
                .Include(p => p.Location).ToListAsync<Person>();
        } else {
            People = Enumerable.Empty<Person>();
        }
    }
        
    string GetEditUrl(long id) => $"/forms/edit/{id}";
        
    public int Counter { get; set; } = 0;
}

Inspect the List.razor implementation that controls when the People query executes and when displayed data refreshes. section 36.3.2

How Pro ASP.NET Core 7, Tenth Edition covers it

How deep it goes
Explains forced evaluation, stored results, and query-side versus in-memory sorting, without descending into asynchronous implementation internals.
Examples
Uses a People List.razor component, an Update button, and database logging to compare explicit refreshes and sorting strategies.
What it assumes
Assumes familiarity with Blazor components and Entity Framework Core queries while demonstrating query evaluation and materialized results.
What you can do after
Apply it via Entity Framework Core to materialize query results and control when a Blazor component re-queries its database.
How it connects
Connects Entity Framework Core, Blazor, IQueryable<T>, LINQ, OrderBy, and component state.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Pro ASP.NET Core 7, Tenth Edition. The section links point to the parts of the book it draws on.