Blazor 服务器和 EF Core:在上一个操作完成之前,已在此上下文实例上启动第二个操作

2024-03-09

我的 ef 核心有问题。我有两个从数据库读取数据的服务。在一个页面上调用第一个服务,在第二个页面上调用第二个服务。当我单击按钮创建新程序时,出现错误。我通常从带有注入服务的页面调用它。有人可以帮我吗?

在应用程序中显示 https://i.stack.imgur.com/9NOmg.png

builder.Services.AddDbContextPool<Context>(options =>
{ 
options.UseSqlServer(builder.Configuration.GetConnectionString("Connection"));
});

测试服务1:

public class TestService1 : ITestService1
{
    private readonly Context _context;
    private readonly IMapper _mapper;

    public TestService1(Context context, IMapper mapper)
    {
        _kreativgangContext = kreativgangContext;
        _mapper = mapper;
    }

    public virtual async Task<AllProgramViewModel> HandleAsync(AllProgramFilterViewModel filter)
    {
        var model = new AllProgramViewModel();

        var data = _context.Programs.Where(x => (EF.Functions.Like(x.Name ?? "", "%" + filter.Name + "%") || string.IsNullOrEmpty(filter.Name)))
            .Select(x => new Core.Models.Program() { ID = x.ID, Name = x.Name, Order = x.Order });

        result.Model.TotalCount = await data.CountAsync();

        result.Model.Items = data.Select(x => _mapper.Map<AllProgramItemViewModel>(x));
    
        return model;
    }
}

public interface ITestService1
{
    public Task<AllProgramViewModel> HandleAsync(AllProgramFilterViewModel filter);
}

测试服务2:

    public class TestService2 : ITestService2
{
    private readonly Context _context;

    public TestService2(Context context)
    {
        _context = context;
    }

    public virtual async Task<NewProgramViewModel> HandleAsync()
    {
        var model = new NewProgramViewModel();

        List<ProgramOrderViewModel> items = _context.Programs.Select(x => new Core.Models.Program() { Order = x.Order, ID = x.ID })
            .Select(x => new ProgramOrderViewModel()
            {
                ID = x.ID,
                Order = x.Order
            }).ToList();

        return await Task.FromResult(model);
    }
}

public interface ITestService2
{
    public Task<NewProgramViewModel> HandleAsync();
}

Error:

Error: System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently 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.
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Mitar.Kreativgang.Admin.Handlers.TestService2.HandleAsync() in D:\Programming\Kreativgang\Src\Mitar.Kreativgang.Admin\Handlers\TestService2.cs:line 26
   at Mitar.Kreativgang.Admin.Pages.Program.ProgramNew.OnInitializedAsync() in D:\Programming\Kreativgang\Src\Mitar.Kreativgang.Admin\Pages\Program\ProgramNew.razor:line 114
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()

这是一个已知且有记录的陷阱,解释于带有 Entity Framework Core (EFCore) 的 ASP.NET Core Blazor 服务器 https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-6.0。在 Blazor Server 中,DI 范围是用户电路 - 本质上是用户会话。这意味着一个scoped服务就像TestService2 or a DbContext将在内存中保留很长时间,并最终被多种方法和操作重用。

正如文档所解释的:

Blazor Server 是一个有状态的应用程序框架。该应用程序保持与服务器的持续连接,并且用户的状态保存在服务器的电路内存中。用户状态的一个示例是在电路范围内的依赖注入 (DI) 服务实例中保存的数据。Blazor Server 提供的独特应用程序模型需要特殊的方法来使用 Entity Framework Core。

您需要注册并使用 DbContextFactory (或PooledDbContextFactory https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.infrastructure.pooleddbcontextfactory-1?view=efcore-6.0) 而不是 DbContextPool,并在使用它的位置创建一个新的 DbContext 实例。

builder.Services.AddDbContextFactory<ContactContext>(opt =>
    opt.UseSqlServer(...));

or

builder.Services.AddPooledDbContextFactory<ContactContext>(opt =>
    opt.UseSqlServer(...));

服务构造函数应该接受工厂而不是上下文:

    public TestService2(AddDbContextFactory<ContactContext> factory)
    {
        _factory = factory;
    }

    public virtual async Task<NewProgramViewModel> HandleAsync()
    {
        
        using var context=_factory.CreateContext())
        {
        ...
        }

    }

组件范围

要将 DbContext 的范围限制为单个组件,仅注入 DbContextFactory 是不够的。当用户离开组件时,需要显式处置 DbContext 实例。为此,组件需要实现 IDisposable。这在本节中进行了解释涵盖组件生命周期 https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-6.0#scope-to-the-component-lifetime

@implements IDisposable
@inject IDbContextFactory<ContactContext> DbFactory
...

@code 
{

    ContactContext? Context;

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

    protected override async Task OnInitializedAsync()
    {
        Context = DbFactory.CreateDbContext();
        ...
    }

}
 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Blazor 服务器和 EF Core:在上一个操作完成之前,已在此上下文实例上启动第二个操作 的相关文章

  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 在 Xamarin 中隐藏软键盘

    如何隐藏软键盘以便在聚焦时显示Entry在 Xamarin forms 便携式表单项目中 我假设我们必须为此编写特定于平台的渲染器 但以下内容不起作用 我创建自己的条目子类 public class MyExtendedEntry Entr
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 根据 N 个值中最小的一个返回不同的结果

    不确定如何使标题更具描述性 所以我只是从一个例子开始 我使用下面的代码位 它从枚举中选择一个方向 具体取决于四个轴中哪一个与给定方向相比形成最小角度 static Direction VectorToDirection Vector2 di
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • C# 构建一个 webservice 方法,它接受 POST 方法,如 HttpWebRequest 方法

    我需要一个接受 POST 方法的 Web 服务 访问我的服务器正在使用 POST 方法 它向我发送了一个 xml 我应该用一些 xml 进行响应 另一方面 当我访问他时 我已经使用 HttpWebRequest 类进行了管理 并且工作正常
  • 如何在服务器端按钮点击时关闭当前标签页?

    我尝试在确认后关闭当前选项卡 因此我将以下代码放在确认按钮的末尾 但选项卡没有关闭 string jScript ClientScript RegisterClientScriptBlock this GetType keyClientBl
  • 检查 RoutedEvent 是否有任何处理程序

    我有一个自定义 Button 类 当单击它时 打开特定窗口 它总是执行相同的操作 我添加了一个可以在按钮的 XAML 中分配的 Click 事件 就像常规按钮一样 当它被单击时 我想执行 Click 事件处理程序 如果已分配 否则我想执行默
  • 在 EnvDTE 中调试时捕获 VS 局部变量

    是否可以使用 EnvDTE 进行 vsix Visual Studio 扩展来捕获本地和调试窗口使用的调试数据 或者可以通过其他方法吗 我想创建一个自定义的本地窗口 我们可以修改它以根据需要显示一些较重的内容 而无需为高级用户牺牲原始的本地
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • 您是否将信息添加到每个 .hpp/.cpp 文件的顶部? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 创建新的 C 头文件 源文件时 您会在顶部添加哪些信息 例如 您是否添加日期 您的姓名 文件描述等 您是否使用结构化格式来存储此信息 e g F
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959
  • 从 JavaScript 中的 OnClientClick 事件中阻止 C# 中的 asp:Button OnClick 事件?

    我有一个asp Button在我的网页上 它调用 JavaScript 函数和代码隐藏方法 后者进行调用以导航到另一个页面 在 JavaScript 函数中 我正在检查条件 如果不满足这个条件 我想中止导航 以便OnClick方法未被调用

随机推荐