GithubHelp home page GithubHelp logo

bubdm / expressioncache Goto Github PK

View Code? Open in Web Editor NEW

This project forked from baune8d/expressioncache

0.0 0.0 0.0 100 KB

ExpressionCache takes advantage of expressions to generate and maintain cache keys for your application.

License: MIT License

C# 100.00%

expressioncache's Introduction

ExpressionCache

Build status codecov

Package Version
ExpressionCache.Core NuGet Badge
ExpressionCache.Distributed NuGet Badge

Dev feed: https://www.myget.org/F/baunegaard/api/v3/index.json

Table of Contents

  1. ExpressionCache.Core
  2. ExpressionCache.Distributed

ExpressionCache.Core

Key generation

The cache key will be a combination of class name, function name and parameter values.

The following code snippet is the heart of the library:

public class SampleService
{
    private readonly IDistributedCacheService _cacheService;
    private readonly SampleRepository _sampleRepository;

    public SampleService(IDistributedCacheService cacheService, SampleRepository sampleRepository)
    {
        _cacheService = cacheService;
        _sampleRepository = sampleRepository;
    }

    public async Task<EntityModel> GetAsync(int entityId, CacheAction cacheAction = CacheAction.Invoke)
    {
        if (cacheAction != CacheAction.Bypass)
        {
            return await _cacheService.InvokeCacheAsync(
                () => GetAsync(entityId, CacheAction.Bypass),
                TimeSpan.FromDays(1), cacheAction);
        }

        return await _sampleRepository.GetAsync(entityId);
    }
}

Flow (Without an existing cache entry)

  1. Lets say we call GetAsync(5) on the above snippet.
  2. cacheAction is not equal to Bypass, so InvokeCacheAsync gets called.
  3. A lookup in cache with generated key {SampleService}{GetAsync}{5}{Bypass} happens.
  4. No cache entry is found so the expression GetAsync(5, CacheAction.Bypass) is invoked.
  5. This time the cache is skipped because of Bypass. Result of sampleRepository is returned.
  6. The returned value gets cached and InvokeCacheAsync returns.

CacheAction enum

  1. Invoke - The default action. Will check for a cached value and return it if found.
  2. Bypass - Used to bypass the caching entirely. Note! Should always be used in the expression to InvokeCache.
  3. Overwrite - Skip checking for cached value, but still cache new value.

Object parameters

If complex objects are used as function parameters, ExpressionCache needs a way to know how to build the key value.

By extending ICacheKey one can define how to build the key.

public class SampleObject : ICacheKey
{
    public int Parameter1 { get; set; }
    public int Parameter2 { get; set; }

    public virtual void BuildCacheKey(ICacheKeyBuilder builder)
    {
        builder
            .By(Parameter1)
            .By(Parameter2);
    }
}

ExpressionCache.Distributed

ExpressionCache use providers to support different caching engines.

Included in this repository is ExpressionCache.Distributed which works with Microsofts IDistributedCache interface.

.NET Core Dependency Injection

The library include extensions for IServiceCollection interface.

public void ConfigureServices(IServiceCollection services)
{
    // Register an IDistributedCache implementation.
    services.AddDistributedRedisCache(options =>
    {
        options.Configuration = "localhost";
        options.InstanceName = "Sample";
    });

    // Register the distributed cache service.
    services.AddDistributedExpressionCache();
}

You can now inject IDistributedCacheService using DI into you code.

Full service example

public class SampleService
{
    private readonly IDistributedCacheService _cacheService;
    private readonly SampleRepository _sampleRepository;

    public SampleService(IDistributedCacheService cacheService, SampleRepository sampleRepository)
    {
        _cacheService = cacheService;
        _sampleRepository = sampleRepository;
    }

    public async Task<bool> CreateAsync(EntityDto entity)
    {
        var newId = await _sampleRepository.CreateAsync(entity);
        if (newId > 0)
        {
            // Add new entity to cache.
            return await GetAsync(newId, CacheAction.Overwrite) != null;
        }
        return false;
    }

    public async Task<bool> UpdateAsync(EntityDto entity)
    {
        if (await _sampleRepository.UpdateAsync(entity))
        {
            // Overwrite cached entity with updated one.
            return await GetAsync(entity.Id, CacheAction.Overwrite) != null;
        }
        return false;
    }

    public async Task<bool> DeleteAsync(int entityId)
    {
        if (await _sampleRepository.DeleteAsync(id)) 
        {
            // Remove cached entity.
            await _cacheService.RemoveAsync(() => GetAsync(entityId, CacheAction.Bypass));
            return true;
        }
        return false;
    }

    public async Task<EntityModel> GetAsync(int entityId, CacheAction cacheAction = CacheAction.Invoke)
    {
        if (cacheAction != CacheAction.Bypass)
        {
            // Check for existing cached entity.
            return await _cacheService.InvokeCacheAsync(
                () => GetAsync(entityId, CacheAction.Bypass),
                TimeSpan.FromDays(1), cacheAction);
        }

        // If not already cached, this result will get cached.
        return await _sampleRepository.GetAsync(entityId);
    }
}

Interface members

The full interface of IDistributedCacheService.

public interface IExpressionCacheBase
{
    string GetKey<TResult>(Expression<Func<TResult>> expression);
    string GetKey<TResult>(Expression<Func<Task<TResult>>> expression);

    TResult InvokeCache<TResult>(Expression<Func<TResult>> expression, TimeSpan expiry, CacheAction cacheAction);
    Task<TResult> InvokeCacheAsync<TResult>(Expression<Func<Task<TResult>>> expression, TimeSpan expiry, CacheAction cacheAction);
}

public interface IDistributedCacheService : IExpressionCacheBase
{
    void Remove<TResult>(Expression<Func<TResult>> expression);
    void Remove<TResult>(Expression<Func<Task<TResult>>> expression);
    Task RemoveAsync<TResult>(Expression<Func<TResult>> expression);
    Task RemoveAsync<TResult>(Expression<Func<Task<TResult>>> expression);

    bool Exists<TResult>(Expression<Func<TResult>> expression);
    bool Exists<TResult>(Expression<Func<Task<TResult>>> expression);
    Task<bool> ExistsAsync<TResult>(Expression<Func<TResult>> expression);
    Task<bool> ExistsAsync<TResult>(Expression<Func<Task<TResult>>> expression);

    TResult Get<TResult>(Expression<Func<TResult>> expression);
    TResult Get<TResult>(Expression<Func<Task<TResult>>> expression);
    Task<TResult> GetAsync<TResult>(Expression<Func<TResult>> expression);
    Task<TResult> GetAsync<TResult>(Expression<Func<Task<TResult>>> expression);

    Task<List<TResult>> GetManyAsync<TResult>(IEnumerable<Expression<Func<TResult>>> expressions);
    Task<List<TResult>> GetManyAsync<TResult>(IEnumerable<Expression<Func<Task<TResult>>>> expressions);

    void Set<TResult, TValue>(Expression<Func<TResult>> expression, TValue value, TimeSpan expiry);
    void Set<TResult, TValue>(Expression<Func<Task<TResult>>> expression, TValue value, TimeSpan expiry);
    Task SetAsync<TResult, TValue>(Expression<Func<TResult>> expression, TValue value, TimeSpan expiry);
    Task SetAsync<TResult, TValue>(Expression<Func<Task<TResult>>> expression, TValue value, TimeSpan expiry);
}

expressioncache's People

Contributors

baune8d avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.