生成一个唯一的缓存键基于方法参数 [英] Generating a unique cache key based on method arguments

查看:204
本文介绍了生成一个唯一的缓存键基于方法参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个最终执行查询,并将结果映射回一个对象,一个基本的仓库框架:

I have a basic repository framework that eventually executes a query and maps the results back into a object:

例如:

    public SomeEntity Get(id)
    {
        return base.GetItem<SomeEntity>
                   ("select * from SomeEntities where id = @idParam",
                    new { idParam = id}); 
    }

如果这看起来像小巧玲珑,那是因为引擎盖下的GetItem的包装小巧精致。

If this looks like Dapper, it is because under the hood GetItem is wrapping Dapper.

我想自动缓存增加的GetItem,我有一个有两个参数:

I'd like to add automatic caching to GetItem, I have two arguments that come in:

  • 包含查询字符串。
  • 包含任何参数的匿名字典。

我很担心,做一个简单的黄金散列这些参数会导致缓存键冲突,当您从缓存中提取数据,冲突可能是非常非常糟糕(IE浏览器泄露敏感 信息)。

I'm worried that doing a simple prime hash on these parameters would cause cache key collisions, and when you are pulling data from a cache, a collision can be very very bad (I.E. leaking sensitive information).

那么,做什么技术我有一个会产生一个合理规模的缓存键,同时保证基于查询和参数的输入独特性?

So, what techniques do I have that would generate a reasonably sized cache key, while guaranteeing uniqueness based on the input of a query and parameters?

推荐答案

我用下面的扩展方法,使代表缓存版本:

I use the following extension methods to make cached versions of delegates:

    public static Func<T, TResult> AsCached<T, TResult>(this Func<T, TResult> function)
    {
        var cachedResults = new Dictionary<T, TResult>();
        return (argument) =>
        {
            TResult result;
            lock (cachedResults)
            {
                if (!cachedResults.TryGetValue(argument, out result))
                {
                    result = function(argument);
                    cachedResults.Add(argument, result);
                }
            }
            return result;
        };
    }

    public static Func<T1, T2, TResult> AsCached<T1, T2, TResult>(this Func<T1, T2, TResult> function)
    {
        var cachedResults = new Dictionary<Tuple<T1, T2>, TResult>();
        return (value1, value2) =>
        {
            TResult result;
            var paramsTuple = new Tuple<T1, T2>(value1, value2);
            lock(cachedResults)
            {
                if (!cachedResults.TryGetValue(paramsTuple, out result))
                {
                    result = function(value1, value2);
                    cachedResults.Add(paramsTuple, result);
                }
            }
            return result;
        };
    }

    public static Func<T1, T2, T3, TResult> AsCached<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> function)
    {
        var cachedResults = new Dictionary<Tuple<T1, T2, T3>, TResult>();
        return (value1, value2, value3) =>
        {
            TResult result;
            var paramsTuple = new Tuple<T1, T2, T3>(value1, value2, value3);
            lock(cachedResults)
            {
                if (!cachedResults.TryGetValue(paramsTuple, out result))
                {
                    result = function(value1, value2, value3);
                    cachedResults.Add(paramsTuple, result);
                }
            }
            return result;
        };
    }

等了N个参数...

And so on for N parameters...

在情况下,它不会从code清楚,我创建一个参数的元组,并使用元组作为一个关键的字典持有的返回值各组参数。请注意,每次调用 AsCached 时,就创建一个单独的缓存。

In case it's not clear from the code, I create a tuple with the arguments, and use the tuple as a key to a dictionary that holds the return values for each set of arguments. Note that every time you call AsCached, you create a separate cache.

您可以使用这些方法如下:

You can use these methods as follows:

private Func<int, SomeEntity> _getCached;

public SomeEntity Get(int id)
{
    if (_getCached == null)
    {
        Func<int, SomeEntity> func = GetImpl;
        _getCached = func.AsCached();
    }
    return _getCached(id);
}

private SomeEntity GetImpl(int id)
{
    return base.GetItem<SomeEntity>
               ("select * from SomeEntities where id = @idParam",
                new { idParam = id}); 
}

这篇关于生成一个唯一的缓存键基于方法参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆