如何在缓存中存储数据?

时间:2018-09-07 11:02:55

标签: c# asp.net asp.net-core asp.net-core-mvc

我创建了一个ViewComponent来显示List<Product>,该列表对来自REST API服务的数据进行了评估,这是我的类实现:

public class ProductsViewComponent : ViewComponent
{
    private readonly HttpClient _client;

    public ProductsViewComponent(HttpClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }

    public async Task<IViewComponentResult> InvokeAsync(string date)
    {
       using (var response = await _client.GetAsync($"/"product/get_products/{date}"))
       {
           response.EnsureSuccessStatusCode();
           var products = await response.Content.ReadAsAsync<List<Product>>();
           return View(products);
       }
    }
}

我将列表加载到Components文件夹Views\Shared\Components\Products\Default.cshtml内的html表中。

在每个需要显示View的{​​{1}}中,我做过:

Products

使用@await Component.InvokeAsync("Products", new { date = myDate }) 中配置的REST API调用HttpClient,如下所示:

Startup.cs

这很好用,但是主要的问题是每次用户重新加载页面或进入需要显示产品列表的另一个View时,应用程序都会进行另一个services.AddHttpClient<ProductsViewComponent>(c => { c.BaseAddress = new Uri('https://api.myservice.com'); }); 调用。

是否可以将列表存储在诸如高速缓存之类的文件中,并且如果日期等于先前选择的日期,则防止再次调用API吗?

我正在学习API,所以我并不是这个论点的专家。

在此先感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

根据Microsoft文档https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-2.1

您可以使用IMemoryCache缓存数据

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();

         services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseMvcWithDefaultRoute();
    }
}

并创建IMemoryCache的实例。这是来自Microsoft文档的示例。您可以创建另一个类来共同处理所有这些,在下面的示例中,这只是保存DateTime,但是,您可以将任何对象保存在缓存中,当您尝试从缓存中读取该值时,只需将该对象转换为Type。

强烈建议您仔细阅读上述文档。

public class HomeController : Controller
{
    private IMemoryCache _cache;

    public HomeController(IMemoryCache memoryCache)
    {
        _cache = memoryCache;
    }

    public IActionResult CacheTryGetValueSet()
    {
       DateTime cacheEntry;

       // Look for cache key.
       if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry))
       {
           // Key not in cache, so get data.
           cacheEntry = DateTime.Now;

           // Set cache options.
           var cacheEntryOptions = new MemoryCacheEntryOptions()
           // Keep in cache for this time, reset time if accessed.
                .SetSlidingExpiration(TimeSpan.FromSeconds(3));

           // Save data in cache.
        _cache.Set(CacheKeys.Entry, cacheEntry, cacheEntryOptions);
      }

      return View("Cache", cacheEntry);
   }

}

更新CacheKeys.Entry是一个静态类,其中定义了所有键。 (只是编码标准)。请检查上面的文档链接。

public static class CacheKeys
{
   public static string Entry { get { return "_Entry"; } }
   public static string CallbackEntry { get { return "_Callback"; } }
   public static string CallbackMessage { get { return "_CallbackMessage"; 
}    }
public static string Parent { get { return "_Parent"; } }
public static string Child { get { return "_Child"; } }
public static string DependentMessage { get { return "_DependentMessage"; 
} }
public static string DependentCTS { get { return "_DependentCTS"; } }
public static string Ticks { get { return "_Ticks"; } }
public static string CancelMsg { get { return "_CancelMsg"; } }
public static string CancelTokenSource { get { return "_CancelTokenSource"; } }}

答案 1 :(得分:1)

您可以使用分布式缓存,因此可以将Redis与ConnectionMultiplexer一起使用。 因此,对于foreach调用,您可以为实现的缓存调用redis,这要归功于这里的接口调用“ IDistributedCache” 您可以找到很多文档来实现缓存并使用它。 :.Net framework
DotNet Core

您的控制器X:

    [HttpGet]
    [Route("{itemId}")]
    public async Task<IHttpActionResult> GetItemById(int eventId, [FromUri]EventTabs tabId)
    {

        ServiceResponse<ItemDto> result = await _itemDispatcher.GetItemById(itemId);

        return WrapResponse(result);
    }

您的调度员通过使用Redis缓存(已实现)的ID来获取项目

 public class ItemDispatcher : ItemDispatcher
{

    private readonly IUnitOfWork _unitOfWork;
    private readonly IDistributedCache _distributedCache; // use interface of your implementation of redis cache

    private readonly int _cacheDuration;
    private readonly bool _isCacheEnabled;

    public EventDispatcher(IUnitOfWork unitOfWork, IDistributedCache distCache)
    {
        _unitOfWork = unitOfWork;

        _distributedCache = distCache; // init cache in constructor


        _cacheDuration = _configuration.Get<int>("cache.duration"); // duration of your cache
        _isCacheEnabled = _configuration.Get<bool>("cache.isEnable"); // if the cache is enable or not
    }



     public async Task<ServiceResponse<ItemDto>> GetItemById(int id)
    {
      // Add this for each Task call
          var cacheKey = string.Empty;

            if (_isCacheEnabled)
            {
                cacheKey = CacheUtils.GetCacheKey(CacheKeys.Item, id);
                itemDto cacheResult = await _distributedCache.Get<ItemDto>(cacheKey);

                if (cacheResult != null)
                    return new ServiceResponse<Item>(cacheResult);
            }
    }