我正在构建一些伪智能缓存到一个 LINQ 查询提供程序 中。理想情况下,我想在某些场景中使用给定查询的表达式树作为缓存键。然而,我不想存储整个对象图本身,那么从表达式树获取类似哈希值的快速方法是什么?或者,如果我走错了方向,有更好的选择吗?
你可以使用这里提供的代码来实现它。 http://petemontgomery.wordpress.com/2008/08/07/caching-the-results-of-linq-queries/
这展示了如何解决闭包问题并支持本地集合。
让我们来思考一下。你想在一个映射中存储(表达式树的哈希值,结果)。
如果不存储整个树,就无法区分相同的树和哈希冲突。
按照定义,哈希将一个更大的集合映射到一个较小的集合中(这就是为什么哈希很有用),所以按照定义,会发生(至少可能发生)冲突。
当你得到一个表达式树时,你会对它进行哈希,然后在映射中查找结果,这会导致两种可能性:
这是一个未在映射中出现过的哈希值。你必须运行它,因为你没有缓存的结果。
这是映射中已经存在的哈希值,但由于你没有在映射中存储生成该哈希值的旧表达式树,因此无法将新传递的表达式与旧表达式进行比较。你可能有一个匹配或者你可能有一个冲突,但无法区分这两种可能性。你不能返回缓存的结果,因为它可能是一个冲突。
hashATree:
if leaf node
return hash(node)
else
return hash(node) *OP* hashATree(left.child) *OP* hashATree(right.child)
其中OP是某个操作(可能是乘法),或更一般地说,hash(node) *OP* accumulate(children.begin(), children.end(), *OP*)
当然,这与我们用于评估表达式树的递归相同(除了我们调用node.eval(children)
)
嗯,实际上我认为这可能相当简单。
Expression对象的ToString()方法将为您提供表达式的文本表示形式,如果您只想评估密钥的等效性,则可以对其进行哈希处理。
1[Quest.Intersect.TestHarness.Customer]).Where(cust => (cust.LastName = "jarvis")).Select(cust => new <>f__AnonymousType1
2(CompID = cust.CompanyID, LastName = cust.LastName)) - Tim Jarvis
.ToString()
。 - Sedat Kapanoglu