英文:
Cannot access a disposed context instance - on the first run
问题
这是一个常见的异常,当尝试访问已释放的上下文时会出现。但是,我在第一次访问上下文时就遇到了这个异常,无法弄清楚为什么会发生这种情况。
这是我用来将上下文注册为“Transient”的代码:
public static IServiceCollection AddSQLContext<TContext>(this IServiceCollection services, string connectionString, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
where TContext : DbContext => services
.AddDbContext<TContext>(options => options.UseSqlServer(
connectionString,
actions => actions.MigrationsAssembly("Discounted.Data")
.EnableRetryOnFailure()
), serviceLifetime);
这是在“Blazor Server”前端中调用服务引发异常的代码:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
using (var source = new CancellationTokenSource())
{
version = VersionService.Version;
ProtectedBrowserStorageResult<string> customer = await ProtectedSessionStore.GetAsync<string>("customer");
DashboardDto.LocalUser = customer.Value;
if (DashboardDto.LocalUser == null) return;
// 获取订阅状态
// ==> 不访问上下文
DashboardDto.LocalStatus = await SubscriptionService.GetSubscriptionStatusAsync(DashboardDto.LocalUser, source.Token);
// 加载图像
// ==> 第一次访问上下文
// ==> 从 GetQRCodeAsync 引发异常
DashboardDto.StoreId = await QRCodeService.GetQRCodeAsync(DashboardDto.LocalUser, source.Token);
// 获取奖励
DashboardDto.Rewards = await RewardService.GetRewardAsync(DashboardDto.StoreId, source.Token);
}
StateHasChanged();
}
}
这是“GetQRCodeAsync”函数和“RewardService”:
public class QRCodeService : IQRCodeService
{
private IAccountRepository _accountRepository;
public QRCodeService(IAccountRepository accountRepository)
{
_accountRepository = accountRepository;
}
public async Task<string?> GetQRCodeAsync(string customerId, CancellationToken cancellationToken)
{
// 在这里引发异常
Account store = await _accountRepository.FirstOrDefaultAsync(x => x.StripeId == customerId, cancellationToken);
return store.StoreCode.ToString();
}
}
我将所有服务和存储库都注册为“Transient”。我不确定是什么原因导致了这个问题,因为这是我能想到的第一次调用后端的地方。
英文:
This is a common exception when one tries to access a disposed context. However, I get this exception the first time I access the context and can't figure out why it would happen.
This is the code I use to register my context as a Transient
public static IServiceCollection AddSQLContext<TContext>(this IServiceCollection services, string connectionString, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
where TContext : DbContext => services
.AddDbContext<TContext>(options => options.UseSqlServer(
connectionString,
actions => actions.MigrationsAssembly("Discounted.Data")
.EnableRetryOnFailure()
), serviceLifetime);
This is the code in Blazor Server
front end that calls the service throwing the exception:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
using (var source = new CancellationTokenSource())
{
version = VersionService.Version;
ProtectedBrowserStorageResult<string> customer = await ProtectedSessionStore.GetAsync<string>("customer");
DashboardDto.LocalUser = customer.Value;
if (DashboardDto.LocalUser == null) return;
// Get the subscription status
// ===> Does not access the context
DashboardDto.LocalStatus = await SubscriptionService.GetSubscriptionStatusAsync(DashboardDto.LocalUser, source.Token);
// Load the image
// ===> Accesses the context for the first time
// ===> Throws Exception from GetQRCodeAsync
DashboardDto.StoreId = await QRCodeService.GetQRCodeAsync(DashboardDto.LocalUser, source.Token);
// Get the rewards
DashboardDto.Rewards = await RewardService.GetRewardAsync(DashboardDto.StoreId, source.Token);
}
StateHasChanged();
}
}
This is the GetQRCodeAsync
function and the RewardService
:
public class QRCodeService : IQRCodeService
{
private IAccountRepository _accountRepository;
public QRCodeService(IAccountRepository accountRepository)
{
_accountRepository = accountRepository;
}
public async Task<string?> GetQRCodeAsync(string customerId, CancellationToken cancellationToken)
{
// Throws Exception here
Account store = await _accountRepository.FirstOrDefaultAsync(x => x.StripeId == customerId, cancellationToken);
return store.StoreCode.ToString();
}
}
I am registering all my services and repositories as Transient
as well. I am unsure what is causing the issue since this is the first call to the back end that I can think of.
答案1
得分: 2
请使用方法OnAfterRenderAsync
代替OnAfterRender
。
您之所以出现错误是因为您在void
函数中执行了异步操作。这意味着主线程不会等待OnAfterRender
函数,而是认为请求已完成,因此会释放dbcontext
。
英文:
Use the method OnAfterRenderAsync
instead of OnAfterRender
.
You are getting an error because you are doing async operation in void function. This means that the main thread will not wait for the function OnAfterRender
and is considering the request completed, therefore disposing the dbcontext.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论