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

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

例如:

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

如果这看起来像Dapper,那是因为引擎盖下的GetItem正在包装Dapper。

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

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

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

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

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

  public static Func AsCached(this Func function) { var cachedResults = new Dictionary(); return (argument) => { TResult result; lock (cachedResults) { if (!cachedResults.TryGetValue(argument, out result)) { result = function(argument); cachedResults.Add(argument, result); } } return result; }; } public static Func AsCached(this Func function) { var cachedResults = new Dictionary, TResult>(); return (value1, value2) => { TResult result; var paramsTuple = new Tuple(value1, value2); lock(cachedResults) { if (!cachedResults.TryGetValue(paramsTuple, out result)) { result = function(value1, value2); cachedResults.Add(paramsTuple, result); } } return result; }; } public static Func AsCached(this Func function) { var cachedResults = new Dictionary, TResult>(); return (value1, value2, value3) => { TResult result; var paramsTuple = new Tuple(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 _getCached; public SomeEntity Get(int id) { if (_getCached == null) { Func func = GetImpl; _getCached = func.AsCached(); } return _getCached(id); } private SomeEntity GetImpl(int id) { return base.GetItem ("select * from SomeEntities where id = @idParam", new { idParam = id}); } 

我看到了一些选择

  1. 将数据打包到类中,使用BinaryFormatter序列化类并对序列化数据执行SHA1哈希,以便为您提供哈希键。

  2. 将数据打包到类中,实现IEqualityComparer,然后可以将其存储在Dictionary中。 通过实现IEqualityComparer,您将控制Hash的生成以及执行的数据比较,以便在发生冲突时识别唯一数据。