gpt4 book ai didi

c# - Blazor:在此之前的操作完成之前,在此上下文中开始了第二次操作

转载 作者:行者123 更新时间:2023-12-03 16:00:13 28 4
gpt4 key购买 nike

我正在创建服务器端Blazor应用程序。以下代码在Startup.cs中。

services.AddDbContext<MyContext>(o => o.UseSqlServer(Configuration.GetConnectionString("MyContext")), ServiceLifetime.Transient);
services.AddTransient<MyViewModel, MyViewModel>();

并在ViewModel中:
public class MyViewModel : INotifyPropertyChanged
{
public MyViewModel(MyContext myContext)
{
_myContext = myContext;
}

public async Task<IEnumerable<Dto>> GetList(string s)
{
return await _myContext.Table1.where(....)....ToListAsync();
}

并在 Razor 文件中。
@inject ViewModels.MyViewModel VM
<input id="search" type="text" @bind="search" />
<input id="search" type="button" value="Go" @onclick="SearchChanged" />
@code {
string search = "";
int currentCount = 0;
async void SearchChanged() {
currentCount++;
dtos = GetList(search);
}
}

但是,有时在单击搜索按钮时会发生以下错误?

System.InvalidOperationException: 'A second operation started on this context before a previous operation completed. This is usually caused by different threads 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.'

最佳答案

编辑过 2020年8月
官方指导:https://docs.microsoft.com/ca-es/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-3.1有几种解决方案。我认为,发布的最佳方法是“创建新的DbContext实例”:

The recommended solution to create a new DbContext with dependencies is to use a factory.


//The factory
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace BlazorServerDbContextExample.Data
{
public class DbContextFactory<TContext>
: IDbContextFactory<TContext> where TContext : DbContext
{
private readonly IServiceProvider provider;

public DbContextFactory(IServiceProvider provider)
{
this.provider = provider;
}

public TContext CreateDbContext()
{
if (provider == null)
{
throw new InvalidOperationException(
$"You must configure an instance of IServiceProvider");
}

return ActivatorUtilities.CreateInstance<TContext>(provider);
}
}
}
注塑厂:
services.AddDbContextFactory<ContactContext>(opt =>
opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db")
.EnableSensitiveDataLogging());
使用工厂:
private async Task DeleteContactAsync()
{
using var context = DbFactory.CreateDbContext();

Filters.Loading = true;

var contact = await context.Contacts.FirstAsync(
c => c.Id == Wrapper.DeleteRequestId);

if (contact != null)
{
context.Contacts.Remove(contact);
await context.SaveChangesAsync();
}

Filters.Loading = false;

await ReloadAsync();
}

我不赞成的答案:
您可以尝试为每个请求创建一个新范围:
public class MyViewModel : INotifyPropertyChanged
{

protected readonly IServiceScopeFactory _ServiceScopeFactory;

public MyViewModel(IServiceScopeFactory serviceScopeFactory)
{
_ServiceScopeFactory = serviceScopeFactory;
}

public async Task<IEnumerable<Dto>> GetList(string s)
{
using (var scope = _ServiceScopeFactory.CreateScope())
{
var referenceContext = scope.ServiceProvider.GetService<MyContext>();
return await _myContext.Table1.where(....)....ToListAsync();
}
}
在以下屏幕截图中,您可以看到此问题的示例案例。用户在几个分页元素中快速单击。在上一个请求结束之前,将开始一个新请求。
Screenshot: it shows how a new request starts before previous one ends
丹尼尔·罗斯(Blazor产品经理)在这里谈论 Using Entity Framework Core with Blazor

关于c# - Blazor:在此之前的操作完成之前,在此上下文中开始了第二次操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58346573/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com