【问题标题】:Blazor A second operation started on this context before a previous operation completedBlazor 在前一个操作完成之前在此上下文上启动了第二个操作
【发布时间】:2020-01-22 13:17:29
【问题描述】:

我动态地制作 NavMenu 并由用户在数据库中返回菜单,并且在索引页面中我已经在数据库中返回了一些内容,但是当我运行应用程序或重新加载它时显示以下错误

InvalidOperationException:在此上下文中启动了第二个操作 在之前的操作完成之前。这通常是由 不同的线程使用相同的 DbContext 实例。更多 有关如何避免 DbContext 线程问题的信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2097913.

导航菜单代码,

List<Menu> menus = new List<Menu>();

protected override async Task OnInitializedAsync()
{ 
    menus  = await MenuService.GetMenus();

}

索引代码

@if (priorities == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Name</th> 
            </tr>
        </thead>
        <tbody>
            @foreach (var priority in priorities)
            {
                <tr>
                    <td>@priority.Name</td>
                </tr>
            }
        </tbody>
    </table>
}

@code { 
    List<Priority> priorities;

    protected override async Task OnInitializedAsync()
    { 
        priorities = await PriorityService.GetPriorities();

    }
}

【问题讨论】:

  • 问题不在您发布的代码中。
  • 显示 GetMenus() 和 GetPriorities() 以及它们如何获取和使用 dbContext。
  • 看起来您正在为两个数据库请求共享相同的 dbcontext 实例。如果您使用 DI,请检查您是否可以使用 transient 而不是 scoped: stackoverflow.com/a/41924039/842935
  • 哇。谢谢 dani herrera,正在工作。
  • 好的。我将其发布为解决方案。

标签: asp.net-core blazor blazor-server-side blazor-client-side


【解决方案1】:

解决方案是使用 `DbContextFactory :

Quoting docs:

某些应用程序类型(例如 ASP.NET Core Blazor)使用依赖注入,但不会创建与所需 DbContext 生命周期一致的服务范围。即使确实存在这种对齐,应用程序也可能需要在此范围内执行多个工作单元。例如,单个 HTTP 请求中的多个工作单元。

在这些情况下,AddDbContextFactory 可用于注册工厂以创建 DbContext 实例。例如:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContextFactory<ApplicationDbContext>(
        options =>
            options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test"));
}

【讨论】:

  • 但是临时上下文会被处理掉吗? (除了 GC 之外)。
  • 如果使用了 OwningComponentBase(参见:docs.microsoft.com/en-us/aspnet/core/blazor/…),当您离开它时,上下文将被索引页处理掉。但是,导航页面将保存上下文,因为除非您重新加载页面,否则您永远不会真正离开它。
  • @HenkHolterman,新技术,新挑战:Using Entity Framework Core with Blazor
  • 我打算编辑以添加该页面的其余部分,但建议的编辑已满。值得指出的是,您使用该 DI 服务的方式也发生了变化,您不能再直接使用它,您必须从中创建实例。
【解决方案2】:

我对 Blazor 服务器应用程序的解决方案是使 ApplicatonDbContext 和服务都瞬态

services.AddDbContext<ApplicationDbContext>(x => x.UseSqlServer(connectionString), ServiceLifetime.Transient);
services.AddTransient<ICustomerService, CustomerService>();

【讨论】:

  • 我同意@Bennyboy1973 的生产环境。但是,如果在单个页面中向用户展示替代组件,那么上述解决方案可能会很有用。
【解决方案3】:

仅当我尝试从多个控件中的同一服务访问用户信息时才收到此错误。有道理——它们在初始化时都在争夺相同的资源。

对我来说,解决方案不是改变范围——而是重新思考我真正在做什么——为什么要使用 2 个单独的控件来尝试访问同一用户的会员功能?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2018-11-07
    • 2021-10-22
    • 2020-03-13
    • 2017-03-14
    • 2021-04-11
    相关资源
    最近更新 更多