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

Blazor中能否像ASP.NET Core MVC一样通过服务操作DbContext?

问题解答
  • 这不是强制要求,但极不推荐你直接沿用ASP.NET Core MVC中的直接注入DbContext的用法,否则大概率会遇到并发异常、数据过期、内存膨胀等难以排查的问题。

为什么MVC里的用法在Blazor Server不适用

ASP.NET Core MVC的Scoped服务生命周期和单个HTTP请求绑定,请求结束就自动释放Scoped的DbContext,不会有长期持有上下文的问题。但Blazor Server的Scoped生命周期是和用户的SignalR长连接绑定的,只要用户不关闭页面,连接就会一直存在,你注入的Scoped DbContext会被持续持有数分钟甚至数小时,会触发以下问题:

  • DbContext本身不是线程安全的,Blazor中用户多次点击、异步事件并发触发时,多个操作同时访问同一个DbContext会直接抛出并发异常
  • 长期存活的DbContext会持续缓存跟踪过的实体,内存占用越来越高,同时读取到的是缓存的过期数据,不会和数据库最新状态同步
  • 容易意外产生长事务,导致数据库锁表、性能下降

改造方案(无需大幅重构原有业务代码)

你不需要完全推翻已写好的GameService逻辑,只要调整依赖注入的对象即可,同时兼容MVC和Blazor场景:

第一步 修改服务注册

// 替换原来的AddDbContextPool,改用工厂注册
services.AddDbContextFactory<AppDbContext>(option => {
    option
    .UseMySql(
        Configuration.GetConnectionString("SqliteConstr"), // 注意此处连接字符串名如果是MySQL建议修改,避免歧义
        new MySqlServerVersion(new Version(5, 5, 62)),
        MysqlOpt => MysqlOpt.EnableRetryOnFailure()
    );
});
// GameService的注册保持不变
services.AddScoped<GameService>();

第二步 改造GameService实现

public class GameService
{
    private readonly IDbContextFactory<AppDbContext> _contextFactory;
    public GameService(IDbContextFactory<AppDbContext> contextFactory)
    {
        _contextFactory = contextFactory;
    }

    public async Task<Game[]> GetGamesAsync()
    {
        // 每个方法内部创建独立的DbContext,using块结束自动释放
        using var DbContext = _contextFactory.CreateDbContext();
        return await DbContext.Games.ToArrayAsync();
    }

    // 其他增删改方法同理,每个操作单独创建上下文即可
}

改造后你原来调用GameService的上层代码完全不需要改动,既可以在MVC中使用,也可以在Blazor组件中直接注入调用,避免了直接操作DbFactory的重复代码。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:27:04