Asp.Net Core + EF Coreでデータをキャッシュするパターン?

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

質問

私はAsp.Net Core + EF Core RESTサービスを持っています。 SPを呼び出すDBのDbContextクラスを作成しました。このメソッドは次のようになります。

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

これはすべて機能しますが、SPが返すデータはめったに変更されないため、毎回SPを呼び出す必要はありません。 24時間ごとにデータを失効させたいと思います。

コアでそれを行うための好ましいパターンがありますか? .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は合法ですか? はい、理由を学ぶ