You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server应用System.ObjectDisposedException异常排查求助

排查并解决Blazor Server中MyDbContext已释放异常

错误描述

System.ObjectDisposedException: 无法访问已释放的上下文实例。此错误的常见原因是将通过依赖注入解析的上下文实例释放后,又在应用的其他位置尝试使用同一实例。这可能是因为您调用了上下文实例的'Dispose'方法,或是将其包裹在using语句中。如果您使用依赖注入,应让依赖注入容器负责处理上下文实例的释放。
对象名称: 'MyDbContext'。

相关代码

模型类

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace SAPConnection.Data
{
    public class LeaveModel
    {
        [Key]
        public int Id { get; set; }
        public String Reason { get; set; } = "";
        public DateTime RequestDate { get; set; } = DateTime.Now;
        public DateTime ToDate { get; set; } = DateTime.Now;

        public DateTime FromDate { get; set; } = DateTime.Now;
        public LeaveTypeModel LeaveType { get; set; }
        [NotMapped]
        public byte[] Attachment { get; set; }
    }
}

public enum LeaveTypeModel
{
    Casual, Sick, Annual
}

LeaveService类

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace SAPConnection.Data
{
    public class LeaveService
    {
        private readonly MyDbContext _context;

        public LeaveService(MyDbContext context)
        {
            _context = context;
        }

        public async Task<List<LeaveModel>> GetLeavesAsync()
        {
            return await _context.leaveModel.ToListAsync();
        }

        public async Task<LeaveModel> GetLeaveAsync(int id)
        {
            return await _context.leaveModel.FindAsync(id);
        }

        public async Task CreateLeaveAsync(LeaveModel leave)
        {
            _context.leaveModel.Add(leave);
            await _context.SaveChangesAsync();
        }

        public async Task UpdateLeaveAsync(LeaveModel leave)
        {
            _context.Entry(leave).State = EntityState.Modified;
            await _context.SaveChangesAsync();
        }

        public async Task DeleteLeaveAsync(int id)
        {
            var leave = await _context.leaveModel.FindAsync(id);
            _context.leaveModel.Remove(leave);
            await _context.SaveChangesAsync();
        }
    }
}

提交请假申请函数

private async Task submitLeaves()
{
    await leaveService.CreateLeaveAsync(newLeave);
    NavigationManager.NavigateTo("/");
}

Program.cs类

using Blazored.Toast;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using SAPConnection.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using SAPConnection.Areas.Identity.Data;
using System.Configuration;

var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("SAPConnectionContextConnection") ?? throw new InvalidOperationException("Connection string 'SAPConnectionContextConnection' not found.");

builder.Services.AddDbContext<SAPConnectionContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true).AddEntityFrameworkStores<SAPConnectionContext>();
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<LeaveService>();

builder.Services.AddBlazoredToast();
var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

问题排查与解决方案

核心原因

Blazor Server中,DbContext默认生命周期为Scoped,但Blazor的SignalR长连接作用域和ASP.NET Core传统请求作用域逻辑不同。如果MyDbContext被手动释放(如调用Dispose、用using块包裹创建),或服务/组件中错误管理了上下文生命周期,后续操作就会触发已释放异常。

具体修复步骤

  1. 确认DbContext注册规范
    当前Program.cs中MyDbContext注册未显式指定生命周期,默认是Scoped,符合Blazor Server要求。可修改为显式注册,提升代码可读性:

    builder.Services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Scoped);
    
  2. 禁止手动管理DbContext生命周期
    检查所有使用MyDbContext的代码,确保没有调用_context.Dispose(),也没有手动new MyDbContext并在using块中使用的情况。依赖注入的上下文实例,生命周期完全由容器负责。

  3. 组件注入方式校验
    确保组件中通过构造函数或属性注入LeaveService,禁止手动创建实例:

    // 组件中正确注入示例
    [Inject]
    public LeaveService leaveService { get; set; }
    [Inject]
    public NavigationManager NavigationManager { get; set; }
    
  4. 优化SubmitLeaves方法
    确认newLeave对象无已释放上下文关联引用,NavigationManager.NavigateTo("/")跳转操作不会导致上下文释放,但需保证CreateLeaveAsync执行完成后无异步操作持有上下文引用。

  5. 特殊场景:使用DbContext工厂
    若服务需在长生命周期组件中多次使用上下文,可改用IDbContextFactory<MyDbContext>创建实例,使用后手动释放:

    • 修改Program.cs注册:
      builder.Services.AddDbContextFactory<MyDbContext>(options => options.UseSqlServer(connectionString));
      
    • 修改LeaveService:
      public class LeaveService
      {
          private readonly IDbContextFactory<MyDbContext> _contextFactory;
      
          public LeaveService(IDbContextFactory<MyDbContext> contextFactory)
          {
              _contextFactory = contextFactory;
          }
      
          public async Task CreateLeaveAsync(LeaveModel leave)
          {
              using var context = _contextFactory.CreateDbContext();
              context.leaveModel.Add(leave);
              await context.SaveChangesAsync();
          }
          // 其他方法同理,用using块创建上下文
      }
      

内容的提问来源于stack exchange,提问作者abraKajapa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 01:24:29