Blazor:在此操作之前,第二项操作已在此上下文上开始

时间:2019-10-11 18:17:45

标签: c# entity-framework entity-framework-core blazor blazor-server-side

我正在创建服务器端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 referenceContext)
    {
        _myContext = myContext;
    }

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

并在剃须刀文件中。

@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:'在上一个操作完成之前,第二个操作在此上下文上开始。这通常是由使用相同DbContext实例的不同线程导致的。有关如何避免DbContext线程问题的更多信息,请参见https://go.microsoft.com/fwlink/?linkid=2097913。'

4 个答案:

答案 0 :(得分:2)

就我而言,我解决了变成AddDbContext ServiceLifetime.Transient

        services.AddDbContext<MY_Context>(options =>
             options.UseSqlServer(
    Configuration.GetConnectionString("DefaultConnection")),
 ServiceLifetime.Transient);

答案 1 :(得分:1)

您可以尝试为每个请求创建一个新范围:

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();
        }
    }

Daniel Roth(Blazor产品经理)在谈论Using Entity Framework Core with Blazor

答案 2 :(得分:0)

错误消息与EF上下文一次不能执行多个操作有关。

我的理解是,如果您在页面上,则可以通过SingalR连接与“服务”文件保持恒定连接。

如果您的页面多次调用该服务,则可能是在完成前一个上下文之前调用了Context执行操作。

我在服务的整个生命周期中没有一个Context实例,而是为每个调用创建了一个实例。似乎可以缓解此问题,但是我不确定它是否被视为“最佳实践”。

例如,

public class MyService
{
    private MyContext Context => new MyContext(new DbContextOptions<MyContext>()));

    private async Task DoSomething()
    {
        await using var context = this.Context;  //New context for the lifetime of this method
        var r = await context.Something
            .Where(d => d....)
            .AsNoTracking()
            .FirstOrDefaultAsync()
            .ConfigureAwait(false);

         // context gets disposed of
         // Other code
    }
    private async Task DoSomethingElse()
    {
        await using var context = this.Context;   //New context for the lifetime of this method
        var r = await context.Something
            .Where(d => d....)
            .AsNoTracking()
            .FirstOrDefaultAsync()
            .ConfigureAwait(false);

         // context gets disposed of
         // Other code
    }
}

答案 3 :(得分:0)

我解决了这个问题,但是我认为我已经失去了工作单位,因为现在我拥有多个dbContex:

构造函数:

private AppDbContext _db;
protected override void OnInitialized()
{
    _db = new AppDbContext();
     var query = _db.Set<Group>().AsQueryable();
}

然后我将其丢弃:

public void Dispose()
{
    _db?.Dispose();
}