首页 > 解决方案 > 为什么我的获取数据查看的是旧数据库数据而不是更新的数据库数据?

问题描述

我有一个计时器,每 10 秒计时一次。计时器结束后,它将调用我的服务,然后从我的服务中获取数据并将其分配给我的 radzen 表,然后 StateHasChanged 将重新渲染页面并更新更改。

@using System.Timers;

Timer _timer;
protected override async Task OnInitializedAsync()
{
      StartTimer();
}

private void StartTimer()
    {
        _timer = new System.Timers.Timer();
        _timer.Interval = 10000; //every 10 seconds
        _timer.Elapsed += DashboardTimerElapsed;

        _timer.Start();

    }

private async void DashboardTimerElapsed(Object source, ElapsedEventArgs e)
    {
        await FetchData();

    }

private async Task FetchData()
    {
        dashboardData = await getDataService.GetDataAsync();
        await InvokeAsync(StateHasChanged);
    }

计时器已过,一切正常,我遇到的唯一问题是如果我的应用程序正在运行,我对数据库中的一个数据进行了更改,例如:将值名称“shazam”更改为“shazamm”。在过去,我的新数据应该拉下“shazamm”,但是当我查看 dashbardData 时,我可以看到它不是拉下“shazamm”,而是拉下“shazam”,我认为这是 dbcontext 的旧实例。(顺便说一句,我的 dbcontext 是作用域) -

services.AddDbContext<DbContext>(options => {
                options.UseSqlServer(Configuration.GetConnectionString("DbContextURL"));
                }, ServiceLifetime.Scoped);

谁能看到我哪里出错并请帮助我?谢谢你!

标签: c#entity-frameworktimer

解决方案


定时器事件将在与定时器实例相同的范围内触发。选项包括:

a) 使用LifetimeScope.Transient,尽管这可能会与其他服务发生冲突,并且它会受益于跨 Scope 共享的实例,尤其是在传递实体的情况下。

b) 在您的计时器内确定 DbContext 实例的范围,而不是依赖使用注入的 DbContext 的共享服务。

c)AsNoTracking()用于您的计时器读取。这将确保从数据库中读取返回的实体。(已通过 EF6 验证,在 EF Core 中应保持一致)这可能意味着在您的服务中引入类似于默认参数的内容,以指示是否附加AsNoTracking()到查询以确保重新读取。

d) 将您的查询基于投影而不是返回实体实例。例如,当您编写要使用的查询.Select().ProjectTo()(Automapper)时,这些将自动返回当前数据库状态,从而避免可能在跟踪实例中的陈旧数据。


推荐阅读