await 执行完毕前的方法 returns
Method returns before await finishes executing
我正在列出 Blazor server side
和 MudBlazor
的数据。
我有一个用户列表:
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 中阅读更多内容。
我正在列出 Blazor server side
和 MudBlazor
的数据。
我有一个用户列表:
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 中阅读更多内容。