根据方法参数生成唯一的缓存键

2024-01-29

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

例如:

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

如果这看起来像 Dapper,那是因为 GetItem 在幕后包装了 Dapper。

我想向 GetItem 添加自动缓存,我有两个参数:

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

我担心对这些参数进行简单的素数哈希会导致缓存键冲突,并且当您从缓存中提取数据时,冲突可能非常非常糟糕(即泄漏敏感数据) 信息)。

那么,我有哪些技术可以生成合理大小的缓存键,同时保证基于查询和参数输入的唯一性?


我使用以下扩展方法来制作委托的缓存版本:

    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 个参数依此类推...

如果代码中不清楚,我会使用参数创建一个元组,并使用该元组作为保存每组参数的返回值的字典的键。请注意,每次您拨打电话时AsCached,您创建一个单独的缓存。

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

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}); 
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据方法参数生成唯一的缓存键 的相关文章

  • 使用 cout 打印字符数组的全部内容

    我对 C 很陌生 只是 Java 的背景不太好 并且对如何打印 char 数组的全部内容感到困惑 我相信我需要使用循环 并将循环基于数组的长度 但我的编译尝试没有成功 这就是我现在所拥有的 在此先感谢您的帮助 include
  • 如何访问 TabControl 选项卡内的控件?

    这就是我到目前为止所拥有的一切 tabControl1 TabPages 0 我的 TabControl 的 TabPage1 中有一个 PictureBox 如何使用代码而不是属性窗格更改图像位置 尽管控件出现在容器内 作为 TabCon
  • 从 QFile 获取句柄

    我有一个QFile 但我需要在其上调用一些仅接受HANDLE 有没有办法找回底层HANDLE of the QFile 我找到了一种使用的方法 get osfhandle 在 MinGW 和 VS 中可用 QFile file HANDLE
  • 多线程中的 OpenCV CascadeClassifier C++ 接口

    我想在多个线程中使用 CascadeClassifier 对象运行 OpenCV C 接口 我的程序的工作方式是我的主线程将 some file xml 加载到 CascadeClassifier 对象中 生成三个或更多线程并向它们传递级联
  • 以十六进制打印字符串? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 这种以十六进制打印字符串的简短方法是
  • 检查 ASP.NET Web 应用程序在运行时是否处于调试模式的首选方法?

    在编译时我可以做这样的检查 if DEBUG Log something endif 但最好检查一下是否debug false 是在运行时在 Web config 中设置的吗 HttpContext IsDebuggingEnabled h
  • 在opencv中将三个灰度[R,G,B]图像合并为单个彩色图像

    我有 3 个使用 split 函数创建的灰度图像 现在我想重新生成彩色图像 我尝试了以下代码 但它不起作用 我得到的结果图像仍然是灰度的 cv Mat R cv imread home r secret R png 0 cv Mat G c
  • Listbox手动DrawItem大字体

    我正在尝试绘制末端是一个的项目 红色字符 并将其删除 字符 并用黑色绘制其他项目 这是我的代码 private void listBox1 DrawItem object sender DrawItemEventArgs e e DrawB
  • C# 中 a+=1 和 a=a+1 的区别

    我发现在C 中a 1不等于a a 1 例如 以下代码编译时不会出现任何错误 字节 b 10 b 5 而下面的代码有编译错误 字节 b 10 b b 5 有人可以告诉我为什么吗 Because b 5变成整数 Int32 主要是因为有重载的可
  • 无法打开包含的文件

    我使用的是 BorlandC 和 Windows 7 当我编译该文件时 出现以下错误 Error Assign C Unable to open include file stdio h Error Assign C Unable to o
  • 友元模板特化声明中不允许使用 Constexpr 吗?

    我正在移植 C 14 constexpr代码库从 Clang 到最新的 g 5 1 考虑以下本土开发的简化代码片段bitset自 Clang 3 3 的太平岁月以来 现在已经快 2 年了 该类就一直可以正确编译 include
  • 如何让一段代码只执行一次?

    我有一个应用程序 其中有多种功能 每个函数都可以根据用户输入多次调用 但是 我只需要在函数中执行一小段代码一次 最初是在应用程序启动时执行 当稍后再次调用同一函数时 不得执行这段特定的代码 代码在VC 请告诉我处理这个问题最有效的方法 使用
  • 如何从 Visual Studio 2012 导出 C# 应用程序以在其他计算机上运行?

    我刚刚在 Visual Studio 2012 中制作了我的第一个 C 应用程序 我想以某种方式导出它 以便其他人可以在他们的计算机 包括没有 Visual Studio 2012 的计算机 中使用它 我该怎么做 我是 C 新手 找不到任何
  • 避免使用一本字典的更好代码 - 区分大小写问题

    我有以下方法用数据读取器的值填充字典 数据读取器字段和传递给方法的属性之间可能存在大小写不匹配的情况 在下面的方法中 我首先将属性转换为小写以解决此问题 这会导致两个字典 有没有更好的方法用一本字典来实现这一目标 private Dicti
  • 如何将逗号分隔的列值与另一个表作为行连接

    我试图通过首先转换我正在成功执行的 SupplierId 列中的逗号分隔值来连接两个表 然而 当我尝试通过外键 DCLink 加入另一个带有供应商名称的表 Vendors 时 问题就出现了 这就是我的意思 原始表的 select 语句 SE
  • 抽象类、构造函数和 Co

    嗯 我正在尝试重用 C 代码的一部分 它是一个带有UDP服务器的抽象类 可以在这里看到 http clutch inc com blog p 4 http clutch inc com blog p 4 我创建了一个像这样的派生类 publ
  • 从 C# 2.0 中的 dll 获取命名空间、类名

    我将动态获取dll 我需要加载 dll 并获取命名空间 类名来调用方法 方法名称是静态的 它将始终为 OnStart 基本上我需要通过加载 dll 来运行一个方法 有人可以帮忙吗 要加载程序集 您可以这样做 Assembly assembl
  • 在 asp.net vb 中通过第一个下拉列表值填充第二个下拉列表

    我在使用 asp net vb 时遇到了一些问题 我想做的是有2个下拉框 第一个下拉菜单将有 1 2 3 例如 第二个下拉菜单将有 A 乙 C 默认情况下 但是 如果选择 1 我希望第二个下拉菜单自动选择 c 我不知道 JavaScript
  • 间歇性“无法解析远程名称”?

    我有一个 ASP NET 应用程序 用它来读取网页的内容HttpWebRequest频繁地 远程地址没有问题 我的应用程序始终工作正常 虽然我没有更改任何内容 但有时 大约每天一次 我会收到此错误 the remote name could
  • Boost C++ 序列化 char *

    我有一个类 我正在尝试序列化一个shared ptr 但序列化对象的正常方法不起作用 class Object public Object Object shared ptr

随机推荐