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

Blazor中调用存储过程第二次时列表数据未正确更新问题

问题解决:Blazor中EF调用存储过程后DateTime列未更新

问题场景

在Blazor应用中使用Entity Framework Core通过存储过程填充数据网格,页面初始化和日期ValueChange事件触发时调用存储过程。首次调用正常,但更改日期后,存储过程接收新日期参数并返回结果,其中重新计算的dataScadenta(DateTime类型)列数据未更新,列表虽有变化但数据不正确。相同存储过程在.NET Framework的EF应用中运行正常。

现有代码

获取数据函数

public async Task<List<TabelRaportari>> GetData(DateTime dataRef)
{
    string dataUWU = dataRef.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
    List<TabelRaportari>? data = null;
    _dbContext.TabelRaportaris.Local.Clear();
    
    data = await _dbContext.TabelRaportaris
                               .FromSqlInterpolated($"EXEC RASF {dataUWU}, null")
                               .ToListAsync();
    return data;
}

模型类

public class TabelRaportari
{
    public int id { get; set; }
    public string? name { get; set; }
    public string? limit {  get; set; }
    public string? obs {  get; set; }
    public DateTime? dataScadenta { get; set; }
}

问题原因

EF Core的**变更跟踪器(Change Tracker)**会缓存已加载的实体。当存储过程返回与之前相同id的实体时,EF Core会优先使用缓存中已存在的实体数据,而非存储过程返回的新数据,导致dataScadenta这类被跟踪的字段无法更新。而.NET Framework中的EF6默认行为或缓存机制与EF Core不同,因此未出现此问题。

_dbContext.TabelRaportaris.Local.Clear()仅清除本地缓存集合,并未移除变更跟踪器中已跟踪的实体,所以无法解决根本问题。

解决方案

方案1:查询时禁用跟踪(推荐)

在查询方法中添加.AsNoTracking(),让EF Core不跟踪从存储过程返回的实体,每次都获取全新的数据:

public async Task<List<TabelRaportari>> GetData(DateTime dataRef)
{
    string dataUWU = dataRef.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
    
    return await _dbContext.TabelRaportaris
                               .FromSqlInterpolated($"EXEC RASF {dataUWU}, null")
                               .AsNoTracking() // 禁用跟踪,跳过缓存
                               .ToListAsync();
}

这种方式简单高效,适合数据网格这类只读场景。

方案2:清空变更跟踪器中的所有实体

如果需要保留实体跟踪,可以在查询前清空变更跟踪器中所有已跟踪的实体:

public async Task<List<TabelRaportari>> GetData(DateTime dataRef)
{
    string dataUWU = dataRef.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
    
    // 解除所有实体的跟踪状态
    foreach (var entity in _dbContext.ChangeTracker.Entries())
    {
        entity.State = EntityState.Detached;
    }
    
    return await _dbContext.TabelRaportaris
                               .FromSqlInterpolated($"EXEC RASF {dataUWU}, null")
                               .ToListAsync();
}

方案3:使用独立的DbContext实例

每次调用GetData时创建新的DbContext实例,避免上下文复用导致的缓存问题:

// 注入DbContext工厂
private readonly IDbContextFactory<YourDbContext> _dbContextFactory;

public YourService(IDbContextFactory<YourDbContext> dbContextFactory)
{
    _dbContextFactory = dbContextFactory;
}

public async Task<List<TabelRaportari>> GetData(DateTime dataRef)
{
    string dataUWU = dataRef.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
    
    using var dbContext = _dbContextFactory.CreateDbContext();
    return await dbContext.TabelRaportaris
                               .FromSqlInterpolated($"EXEC RASF {dataUWU}, null")
                               .ToListAsync();
}

此方法适合需要隔离上下文的场景,但会增加上下文创建开销。

额外检查点

  • 确认存储过程返回的dataScadenta列名称与模型属性完全匹配(注意数据库是否区分大小写)。
  • 直接在数据库工具(如SSMS)中执行存储过程,验证传入新日期后是否返回正确的dataScadenta值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 22:12:37