在Asp.Net Core + EF Core中緩存數據的模式?

asp.net-core c# entity-framework-core

我有一個Asp.Net Core + EF Core REST服務。我為要調用SP的數據庫創建了一個DbContext類。該方法幾乎看起來像:

public IQueryable<xxx> Getxxxs()
{
    return Set<xxx>().FromSql("pr_Getxxx");
}

這一切都有效,但是每次調用SP都沒有任何意義,因為SP返回的數據很少發生變化。我想讓數據陳舊,每24小時說一次。

在Core中有沒有首選模式?我看到他們有.AddCaching擴展方法,但似乎它會注入控制器?那麼它的控制器工作要緩存嗎?我認為它的線程安全所以我不需要做任何鎖定或類似的東西?看起來像競爭條件,如果一個線程正在檢查項目是否已加載到緩存中,另一個可能正在插入它,等等?

熱門答案

好吧,你可以應用裝飾模式 。它不是.NET Core特有的,只是一種常見的模式。

public class MyModel
{
    public string SomeValue { get; set; }
}

public interface IMyRepository
{
    IEnumerable<MyModel> GetModel();
}

public class MyRepository : IMyRepository
{
    public IEnumerable<MyModel> GetModel()
    {
        return Set<MyModel>().FromSql("pr_GetMyModel");
    }
}

public class CachedMyRepositoryDecorator : IMyRepository
{
    private readonly IMyRepository repository;
    private readonly IMemoryCache cache;
    private const string MyModelCacheKey = "myModelCacheKey";
    private MemoryCacheEntryOptions cacheOptions;

    // alternatively use IDistributedCache if you use redis and multiple services
    public CachedMyRepositoryDecorator(IMyRepository repository, IMemoryCache cache)
    {
        this.repository = repository;
        this.cache = cache;

        // 1 day caching
        cacheOptions = new MemoryCacheEntryOptions()
            .SetAbsoluteExpiration(relative: TimeSpan.FromDays(1));
    }

    public IEnumerable<MyModel> GetModel()
    {
        // Check cache
        var value = cache.Get<IEnumerable<MyModel>>("myModelCacheKey");
        if(value==null)
        {
            // Not found, get from DB
            value = Set<MyModel>().FromSql("pr_GetMyModel").ToArray();

            // write it to the cache
            cache.Set("myModelCacheKey", value, cacheOptions);
        }

        return value;
    }
}

由於ASP.NET Core DI不支持攔截器或裝飾器,因此您的DI註冊將變得更加冗長。或者使用支持裝飾器註冊的第三方IoC容器。

services.AddScoped<MyRepository>();
services.AddScoped<IMyRepository, CachedMyRepositoryDecorator>(
    provider => new CachedMyRepositoryDecorator(
        provider.GetService<MyRepository>(),
        provider.GetService<IMemoryCache>()
    ));

這樣做的好處是可以清楚地分離關注點,並可以通過將DI配置更改為輕鬆禁用緩存

services.AddScoped<IMyRepository,MyRepository>();


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因