对象在缓存场景中被释放问题

huangapple go评论135阅读模式
英文:

Object disposed problem in caching scenario

问题

我写了一个启用对象缓存的类,可以在一定时间内缓存对象。Cache.cs 类使用委托来刷新缓存中的数据,如果超过了指定的时间。

例如,我有一个名为 DatumService 的类,它保存了来自名为 Datum 的表的所有行。这个表几乎不会改变,所以将它们保留在内存中是安全的。我将过期时间设置为 1 小时。

在一个小时后,会调用下面的例程。

/// <summary>
/// 获取所有要缓存的 Datum 记录。
/// </summary>
private List<Datum> GetDatums()
{
    return ModelContext
        .Datums
        .AsNoTracking()
        .ToList();
}

这个方法使用 Entity Framework 进行调用,以重新填充缓存中的所有 "Datum" 行。

我遇到的问题与 ModelContext 的当前实现有关。

Datum 服务消耗了 ServiceBase 类,该类注入了 IServiceProvider。

private IServiceProvider _serviceProvider { get; set; } = default!;

public ServiceBase(IServiceProvider provider)
{
    _serviceProvider = provider;
}

public ModelContext? ModelContext => _serviceProvider.GetService<ModelContext>();

以前我将 ModelContext 注入到这个类中,但会导致相同的问题。

ModelContext 是从 Microsoft 的依赖注入中获取的。当缓存过期并进行调用时,我会在 IServiceProvider 对象上收到 "对象已处置" 异常。

如何解决这个问题?

英文:

I've written a class that enables caching of objects for a certain amount of time. The Cache.cs class uses a delegate to refresh the data in the cache if this time period expires.

I have for instance a class called DatumService which holds all the rows from a table called Datum. This table hardly ever changes so it safe to keep them in memory. I've set the expiration to 1 hour.

After an hour the routine below is called.

    /// &lt;summary&gt;
    /// Gets all Datum records to be cached.
    /// &lt;/summary&gt;
    private List&lt;Datum&gt; GetDatums()
    {
        return ModelContext
            .Datums
            .AsNoTracking()
            .ToList();
    }

This method makes a call using the Entity Framework to refill the cache with all 'Datum' rows.

The problem I have is with the current implementation of ModelContext.

The Datum service consumes the ServiceBase class which gets injected with the IServiceProvider.

    private IServiceProvider _serviceProvider { get; set; } = default!;

    public ServiceBase(IServiceProvider provider)
    {
        _serviceProvider = provider;
    }
	
    public ModelContext? ModelContext =&gt; _serviceProvider.GetService&lt;ModelContext&gt;();

Earlier I injected the ModelContext into this class but that causes the same problem.

The ModelContext is received from Microsofts Dependency Injection. When the cache expires and the call is made I get an 'Object Disposed' exception on the IServiceProvider object.

How can I solve this problem?

答案1

得分: 1

看起来你的 ModelContextIServiceProvider 是从某个范围中解析出来的,而这个范围在你想要刷新缓存时已经结束,导致观察到的行为(范围会在范围完成时清理掉它创建的所有瞬态和作用域服务)。修复这个问题的一种方法是注入 IServiceScopeFactory,并在需要刷新缓存时创建范围:

private IServiceProvider _scopeFactory { get; set; };

public CacheRefreshingService(IServiceScopeFactory scopeFactory)
{
    _scopeFactory = scopeFactory;
}

private List<Datum> GetDatums()
{
    using var scope = _scopeFactory.CreateScope();
    var ctx = scope.ServiceProvider.GetRequiredService<ModelContext>();
    return ModelContext
        .Datums
        .AsNoTracking()
        .ToList();
}

但我建议稍微重构整个代码(没有看到代码的情况下很难具体指导)。

英文:

It seems that your ModelContext and IServiceProvider are resolved from some scope which ends by the time you want to refresh the cache resulting in the observed behaviour (scope will dispose all transient and scoped services created by it on scope completion). One way to fix this is to inject IServiceScopeFactory and create scope when cache needs to be refreshed:

private IServiceProvider _scopeFactory { get; set; };

public CacheRefreshingService(IServiceScopeFactory scopeFactory)
{
    _scopeFactory = scopeFactory;
}

private List&lt;Datum&gt; GetDatums()
{
    using var scope = _scopeFactory.CreateScope();
    var ctx = scope.ServiceProvider.GetRequiredService&lt;ModelContext&gt;();
    return ModelContext
        .Datums
        .AsNoTracking()
        .ToList();
}

But I would suggest to look into refactoring the whole thing a bit (it is hard to say how exactly without seeing the code)

huangapple
  • 本文由 发表于 2023年3月7日 03:45:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75655190.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定