[英]Pattern for caching data in Asp.Net Core + EF 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 = repository.GetModel();
// write it to the cache
cache.Set("myModelCacheKey", value, cacheOptions);
}
return value;
}
}
由於 ASP.NET Core DI 不支持攔截器或裝飾器,因此您的 DI 注冊將變得更加冗長。 或者使用支持裝飾器注冊的 3rd 方 IoC 容器。
services.AddScoped<MyRepository>();
services.AddScoped<IMyRepository, CachedMyRepositoryDecorator>(
provider => new CachedMyRepositoryDecorator(
provider.GetService<MyRepository>(),
provider.GetService<IMemoryCache>()
));
這樣做的好處是您可以清楚地分離關注點,並且可以通過將 DI 配置更改為
services.AddScoped<IMyRepository,MyRepository>();
你可以使用這個第三方包: https : //github.com/VahidN/EFSecondLevelCache.Core
使用 AspNetCore MW 和 EfCore 擴展(可緩存),如下所示:
var posts = context.Posts
.Where(x => x.Id > 0)
.OrderBy(x => x.Id)
.Cacheable()
.ProjectTo<PostDto>(configuration: _mapper.ConfigurationProvider)
.ToList();
ProjectTo<>() 是 AutoMapper 擴展。
有一個二級緩存擴展可以做你想做的事。 它被稱為EntityFrameworkCore.Cacheable (是的,它是由我創建的,因為我遇到了類似的問題)。
這里有一個基於擴展使用的示例:
var cacheableQuery = cacheableContext.Books
.FromSql("pr_Getxxx")
.Cacheable(TimeSpan.FromHours(24));
Cacheable(...
方法調用將第一個結果存儲到內存緩存中,如果再次調用相同的 linq 表達式,則返回緩存的結果 24 小時。
您可以使用 ASP.Net Core Memory Cache 來緩存數據。 然后您可以根據需要設置滑動/絕對到期時間。 參考 MemoryCahe 的文檔https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-5.0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.