哈希表达式树

时间:2009-04-17 00:17:34

标签: .net linq expression-trees

我正在构建一些伪智能缓存到LINQ query provider。我想做的(理想情况下)是在某些情况下使用给定查询的表达式树作为缓存键。但是,我不想存储整个对象图本身,那么从表达式树中获取类似hashsum的值的快速方法是什么?或者,如果我走向错误的方向,是否有更好的选择?

3 个答案:

答案 0 :(得分:1)

让我们考虑一下。大概你想在地图中存储(表达式树的哈希,结果)。

如果不存储整个树,则无法区分相同的树和哈希冲突。

根据定义,散列将较大的集合映射到较小的集合(这就是散列有用的原因),因此根据定义,您将(至少可能发生)冲突。

获得表达式树后,您将对其进行哈希处理,然后在地图中查找结果,这会产生两种可能性:

  1. 这是一个不在地图中的哈希,一个你以前没见过的哈希。你必须让这个运行,因为你没有缓存的结果。

  2. 它是地图中的哈希值,但由于您没有存储在地图中产生哈希值的旧表达式树,因此无法将新传递的表达式与旧表达式进行比较。您可能有匹配或者您可能发生了碰撞,但是没有办法区分这两种可能性。您无法返回缓存的结果,因为它可能是碰撞。

  3. 此外,即使它不是碰撞,即使它与你上次看到的表达树完全相同,我们怎么知道支持对象 - 数据库,列表,等等*没有添加,删除或修改元素,使表达式返回的结果可能与缓存的结果不同?

    也就是说,你可以递归地散列树:

    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);

答案 1 :(得分:1)

您可以使用此处提供的代码执行此操作。 http://petemontgomery.wordpress.com/2008/08/07/caching-the-results-of-linq-queries/

这显示了如何解决闭包问题并支持本地收藏。

答案 2 :(得分:-1)

嗯,实际上我觉得这可能很简单。

Expression对象的ToString()方法将为您提供Expression的文本表示,如果您想要的只是评估键的等效性,您可以哈希表示。