await 执行完毕前的方法 returns

Method returns before await finishes executing

我正在列出 Blazor server sideMudBlazor 的数据。
我有一个用户列表:

UserList.razor

public partial class UserList
{
    private async Task<TableData<User>> ServerReload(TableState state)
    {
        var admTableData = await _userService.GetUsersAsTableDataAsync(state.ToAdmTableState());
        return admTableData.ToTableData();
    }
}

用户列表的服务如下所示:

UserService.cs

public class UserService
{
    public UserService(MyDbContext myDbContext)
    {
        _userRepository = new UserRepository(myDbContext);
    }

    public Task<AdmTableData<User>> GetUsersAsTableDataAsync(AdmTableState admTableState)
    {
        var queryable = _userRepository.GetUsersAsQueryable();

        if (!string.IsNullOrEmpty(admTableState.SearchString))
        {
            queryable = queryable.Where(u => u.Name.Contains(admTableState.SearchString, StringComparison.OrdinalIgnoreCase));
        }

        switch (admTableState.SortLabel)
        {
            case "Name":
                queryable = queryable.OrderByDirection(admTableState.SortDirection, o => o.Name);
                break;
        }

        return PaginationHelper.GetTableDataAsync(queryable, admTableState);
    }
}

pagination 帮手:

PaginationHelper.cs

public static async Task<AdmTableData<T>> GetTableDataAsync<T>(IQueryable<T> queryable, AdmTableState admTableState)
{
    var admTableData = new AdmTableData<T>();

    admTableData.TotalItems = await queryable.CountAsync();

    admTableData.Items = await queryable.Skip(admTableState.PageNumber * admTableState.PageSize)
        .Take(admTableState.PageSize).ToListAsync();

    return admTableData;
}

最后。我正在通过以下方式注册 services

Program.cs

builder.Services.AddDbContext<MyDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("myConnectionString")));

builder.Services.AddScoped<IUserService, UserService>();

如果我订购专栏。我收到此错误:

Error: System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.

如果我搜索一下。它从不获取数据并不断加载:

Loading forever screenshot

如果您在服务器端使用 Blazor,则必须使用 IDbContextFactory,因为您不能在多个线程中多次使用同一个 dbcontext 实例。

您的 dbcontext 服务是有范围的,这意味着它会在向服务器发出新请求时创建一个新实例,但是 Blazor 服务器是单页应用程序并且您有一个请求和一个 dbcontext 实例,如果您像普通 asp.net 核心应用程序一样使用相同的 dbcontext 它会给你这个错误:

Error: System.InvalidOperationException: A second operation was started on this....

您必须手动创建 dbcontext 实例。像这样注册您的 dbcontext:

builder.Services.AddDbContextFactory<MyDbContext>(
     options => options.UseSqlServer(builder.Configuration.GetConnectionString("myConnectionString")));

并像这样在您的代码中使用它:

private readonly IDbContextFactory<MyDbContext> _contextFactory;

public MyController(IDbContextFactory<MyDbContext> contextFactory)
{
    _contextFactory = contextFactory;
}

public void DoSomething()
{
    using (var context = _contextFactory.CreateDbContext())
    {
        // ...
    }
}

您可以在 DbContext Lifetime, Configuration, and Initialization 中阅读更多内容。