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

Blazor .NET 8应用SignalR更新后数据不显示问题排查

问题分析与解决方案

问题根源

核心原因是EF Core的上下文跟踪缓存机制:当View页面首次加载时,EF Core的ApplicationDbContext会跟踪加载的Debtor实体实例。当Edit页面更新数据库中的数据后,View页面通过SignalR触发RefreshData执行查询时,EF Core会直接返回上下文缓存中的旧实体,而非从数据库获取最新数据。这种情况在.NET 8的Interactive Server模式下更易显现,因为该模式下组件的生命周期更长,上下文缓存的实体不会被及时清理。

解决方案

方案1:关闭查询跟踪(推荐)

修改Repository中的查询方法,添加AsNoTracking(),确保每次查询都跳过上下文缓存,直接从数据库获取最新数据:

public class Repository<T> : IRepository<T> where T : class
{
    private ApplicationDbContext _db;
    public Repository(ApplicationDbContext db)
    {
        _db = db;
    }

    public async Task<T> GetSingleOrDefaultWhereIncludeAsync(Expression<Func<T, bool>> where, string include)
    {
        // 添加AsNoTracking()关闭跟踪
        return await _db.Set<T>().Include(include).AsNoTracking().SingleOrDefaultAsync(where);
    }
}

方案2:分离旧实体(如需保留跟踪场景)

如果业务需要保持实体跟踪(比如后续要修改该实体),可以在RefreshData方法中先将旧的_debtor实例从上下文分离,再执行查询:

private async Task RefreshData(bool? firstrender = false)
{
    // 分离旧的跟踪实体
    var entry = _db.Entry(_debtor);
    if (entry.State != EntityState.Detached)
    {
        entry.State = EntityState.Detached;
    }
    
    _debtor = await _debtorRepos.GetSingleOrDefaultWhereIncludeAsync(x => x.Deleted == false && x.Id == DebtorId, "Contacts");
    StateHasChanged();
}

额外验证

确保ApplicationDbContext的注册方式为Scoped(Blazor Server的默认推荐生命周期),避免因上下文单例导致的全局缓存问题:

// Program.cs中的DbContext注册
builder.Services.AddDbContext<ApplicationDbContext>(options => 
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")), 
    ServiceLifetime.Scoped);

为什么.NET 7正常?

在.NET 7的Blazor Server模式下,组件的Scoped生命周期与上下文的匹配度更高,组件销毁时上下文也会被及时回收,缓存的实体不会长期存在。而.NET 8的Interactive Server模式优化了组件存活机制,上下文缓存的问题更容易暴露。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:25:25