Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get cache key generated and used by FromCache #818

Open
fenomeno83 opened this issue Nov 24, 2024 · 8 comments
Open

Get cache key generated and used by FromCache #818

fenomeno83 opened this issue Nov 24, 2024 · 8 comments
Assignees

Comments

@fenomeno83
Copy link

fenomeno83 commented Nov 24, 2024

In there a manner to get generated cachekey (based on query and parameters) by FromCache/FromCacheAsync?

I'd like send cache data via api to all other nodes, so when a node execute query, set own cache (automatically with FromCache), and send the cache data with cache key to all other nodes.
So all other nodes if execute query with same parameters using FromCache, no need to execute on database because use cache (that has sent the first node).

Is a manner to sicronize cache without use a distribuited server cache

Thanks

@fenomeno83 fenomeno83 changed the title Get cache key generated and user by FromCache Get cache key generated and used by FromCache Nov 24, 2024
@JonathanMagnan JonathanMagnan self-assigned this Nov 25, 2024
@JonathanMagnan
Copy link
Member

Hello @fenomeno83 ,

I'm not sure if that will answer your question or not but:

You can create your own cache key by using this factory: https://github.com/zzzprojects/EntityFramework-Plus/blob/master/src/shared/Z.EF.Plus.QueryCache.Shared/QueryCacheManager.cs#L209

Or you can create your own implementation of the ObjectCache by inheriting from it and setting your new cache to this following property: https://github.com/zzzprojects/EntityFramework-Plus/blob/master/src/shared/Z.EF.Plus.QueryCache.Shared/QueryCacheManager.cs#L68, so you will be able to control how to cache retrieve value to have the behavior you describe.

Let me know if that answers your question.

Best Regards,

Jon

@fenomeno83
Copy link
Author

fenomeno83 commented Nov 25, 2024

Thanks for response!
So, you don't expose as output something in FromCache to know what key has created automatically? And something output bool properties that says that key is new (because query on db and create cache key) or is old key so FromCache has used cache?

So I'd like have as FromCache output these 2 info that says what FromCache has done.

@fenomeno83
Copy link
Author

fenomeno83 commented Nov 25, 2024

something like this (see key and isNewKey)

   public async Task<List<CountryDto>> GetCountries()
   {
        string key = null;
        bool isNewKey = false;
        var ret = (await (from c in _db.Country
                    select new CountryDto()
                    {
                        Code = c.Code,
                        Description = c.Description

                    }).FromCacheAsync(new MemoryCacheEntryOptions() 
                       { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24) }, 
                            "Countries", out key, out isNewKey)).ToList();

        return ret;
  }

So, if fromcache make to this automatically I'd like know what has done, without make a my implementation

@JonathanMagnan
Copy link
Member

Hello @fenomeno83 ,

Unfortunately, we do not expose what you are looking for directly from the method.

But if you look at our implementation, you could probably create your own method as everything you need is public and you have access to it.

For example:

Best Regards,

Jon

@fenomeno83
Copy link
Author

fenomeno83 commented Nov 25, 2024

Ok thanks, in this manner I can get the 2 info

 public async Task<List<CountryDto>> GetCountries()
 {

       var query = from c in _db.Country
                   select new CountryDto()
                   {
                        Code = c.Code,
                        Description = c.Description

                   };

       var key = QueryCacheManager.GetCacheKey(query, ["Countries"]);

       bool exist =  QueryCacheManager.Cache.TryGetValue(key, out _);

       var ret = (await (query).FromCacheAsync(new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24) }, "Countries")).ToList();

       if (!exist)
       {
         QueryCacheManager.Cache.TryGetValue(key, out object result);

         //send result to key of other nodes that expose and api that SetValue
       }

       return ret;

  }

@fenomeno83
Copy link
Author

fenomeno83 commented Nov 25, 2024

So, I've created and extension method that wraps FromCacheAsync and do what I need

This is the original query

 public async Task<List<CountryDto>> GetCountries()
 {
   
    return (await (from c in _db.Country
                select new CountryDto()
                {
                    Code = c.Code,
                    Description = c.Description

                }).FromCacheAsync(new MemoryCacheEntryOptions() 
                   { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24) }, 
                        "Countries")).ToList();

}

It became:

  public async Task<List<CountryDto>> GetCountries()
  {
   
     return (await (from c in _db.Country
                select new CountryDto()
                {
                    Code = c.Code,
                    Description = c.Description

                }).FromCacheWrappedAsync(new MemoryCacheEntryOptions() 
                   { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24) }, 
                        "Countries")).ToList();

 }

public static class QuerableExtensions
{
  public static async Task<IEnumerable<T>> FromCacheWrappedAsync<T>(this IQueryable<T> query, 
  MemoryCacheEntryOptions options, params string[] tags) where T : class
  {
    var key = QueryCacheManager.GetCacheKey(query, tags);

    bool exist = QueryCacheManager.Cache.TryGetValue(key, out _);

    var ret = await query.FromCacheAsync(options, tags);

    if (!exist)
    {
        QueryCacheManager.Cache.TryGetValue(key, out object result); //maybe I can skip this and send "ret" to api on nodes

        //send "result" or "ret" to key of other nodes that expose and api that SetValue
    }

    return ret;
 }
}

@JonathanMagnan
Copy link
Member

Hello @fenomeno83 ,

Awesome, I'm happy you succeeded in making it work.

Can we close this issue as I don't think at this moment we will include it in our base library?

Best Regards,

Jon

@fenomeno83
Copy link
Author

Yes..thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants