I'm building a Blazor Server app using .NET 6. As an example I have a list of customers that I retrieve from a Sqlite db using Entityframework Core. I want to show a loading indicator when the data is still being retrieved. Like so:
@page "/customers"
@inject CustomerService CustomerService
@if(customers.Count == 0)
{
<p>Loading...</p>
}
else
{
<table>
@foreach(Customer customer in customers)
{
<tr>
<td>
@customer.Id
</td>
<td>
@customer.Name
</td>
</tr>
}
</table>
}
When I use following data implementation it works fine:
private List<Customer> customers = new();
protected async override Task OnInitializedAsync()
{
await Task.Run(() =>
{
this.customers = CustomerService.GetCustomers();
});
}
However when I use following data implementation it doesn't work. Meaning that the entire page only becomes visible once the data has been loaded (white page while waiting).
private List<Customer> customers = new();
protected async override Task OnInitializedAsync()
{
this.customers = await CustomerService.GetCustomersAsync();
}
CustomerService.cs
public class CustomerService
{
private CustomerContext _customerContext;
public CustomerService(CustomerContext customerContext)
{
_customerContext = customerContext;
}
public async Task<List<Customer>> GetCustomersAsync()
{
return await _customerContext.Customers.ToListAsync();
}
public List<Customer> GetCustomers()
{
return _customerContext.Customers.ToList();
}
}
I would expect my second implementation to also work asynchronously. Could anyone help me understand please? What am I missing here? Thanks in advance for the help!
CodePudding user response:
It depends on your database if ToListAsync()
really/always is async. It may execute synchronously, depending on the provider, caching etc.
There is a simple fix:
private List<Customer> customers = new();
protected async override Task OnInitializedAsync()
{
await Task.Delay(1);
this.customers = await CustomerService.GetCustomersAsync();
}
The async Delay() allows the loading... message to be displayed.
Note that you might as well call GetCustomers()
, without the Task.Run() though.
... from a Sqlite db
Here is an answer about sqlite, it does not actually support async operations. The EF provider just pretends.