首页 > 解决方案 > Blazor 服务器和实体框架。如何避免对数据库的多次冲突调用

问题描述

概括

在我的 Razor 页面中,单个用户操作会触发两个事件。这些事件导致调用 EF 导致错误:

System.InvalidOperationException HResult=0x80131509 Message=在前一个操作完成之前在此上下文中启动了第二个操作。这通常是由使用相同 DbContext 实例的不同线程引起的。

设置 我没有一个巨大的 DBContext,而是有多个上下文,每个上下文都专注于数据库中的一小部分功能。所以,让我们想象一下,在这里我正在处理与 People 一起工作的功能。

因此,我有一个 PeopleContext 和一个 PeopleService。在我的启动中,这些注册为:

services.AddDbContext<PeopleContext>();
services.AddScoped<PeopleService>();

并且上下文被注入到服务中:

public class PeopleService
{
    public PeopleService(PeopleContext context)
    {
        this.Context = context;
    }

    private PeopleContext Context { get; }

行动

因此,想象一个页面,左侧有一个网格,显示每个人的摘要,右侧有一个区域,我们显示所选人员的详细信息。

当有人单击网格的一行时,我们会调用服务以加载该人的全部详细信息并在右侧显示该数据。

我们在网格上还有一个 [Edit] 按钮。当有人点击它时,它会打开一个模式窗口。该窗口调用 SAME 服务上的 SAME 方法(因此使用 SAME 上下文)以加载完整的详细信息,以便我们可以编辑此人。

所以,我的问题当然是当有人点击 Grid 中的 [Edit] 按钮时,他们也在选择当前行,因此该方法几乎同时被调用两次,导致上述冲突。

解决方案

我不认为我想引入锁定的概念,因为这会导致性能问题。我也不想在不同的服务中复制该方法,因为我想让我的代码保持干燥。我不确定当有人单击行上的按钮时不触发 SELECT ROW 事件是否有意义。我也不能是第一个遇到这种情况的人,所以必须有一个既定的“最佳实践”来处理这种行为——因此这篇文章希望能发现那是什么。


使用:Blazor 服务器、.NET 3.1

标签: entity-frameworkentity-framework-coreblazor-server-side

解决方案


最终解决方案是:

剃刀页面

@inherits OwningComponentBase<Data.MyService>

启动

services.AddDbContext<MyContext>();
services.AddScoped<MyService>();

有关更多详细信息,请参阅:将 Entity Framework Core 与 Blazor #10448 一起使用


推荐阅读