【问题标题】:Hashing an expression tree散列表达式树
【发布时间】:2009-04-17 00:17:33
【问题描述】:

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

【问题讨论】:

    标签: .net linq expression-trees


    【解决方案1】:

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

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

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

    当你得到一个表达式树时,你会对它进行哈希处理,然后在你的地图中查找一个结果,这会导致两种可能性:

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

    2. 它是映射中的哈希,但由于您没有将产生哈希的旧表达式树存储在映射中,因此无法将新传递的表达式与旧表达式进行比较。您可能会遇到匹配或冲突,但无法区分这两种可能性。您无法返回缓存的结果,因为它可能是冲突。

    此外,即使它不是冲突,即使它是与您上次看到的完全相同的表达式树,我们如何知道支持对象 - 数据库,列表,任何*没有添加或删除或修改元素,使得表达式返回的结果可能与缓存的结果不同?

    也就是说,您可以递归地散列一棵树:

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

    【讨论】:

    • 吹毛求疵,散列并不总是从大集合到小集合,例如完美散列。
    • 您关于碰撞的观点在理论上是正确的,但实际上也无关紧要。 MD5 和 SHA 也有可能发生冲突,但我们仍然使用它们,因为它们很实用。我需要一个实用的哈希,而不是数学上防碰撞的哈希。
    • 为了回答您关于后备存储同步问题的问题,我已经解决了这些问题。但是,我对使用当前的缓存键控方法(存储表达式树本身)进行生产感到不舒服
    【解决方案2】:

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

    这展示了如何解决闭包问题并支持本地集合。

    【讨论】:

    • 如果您可以在此处包含相关位,那就太好了。人们来这里是为了答案,而不是链接……除非你能保证你的博客会永远存在,否则这个答案一旦出现故障就会变得毫无用处。
    • 嗯,他基本上使用.ToString()
    【解决方案3】:

    嗯,实际上我认为这可能很简单。

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

    【讨论】:

    • 这并没有包含表达式树的完整哈希...许多表达式树具有相同的字符串值,但底层节点不同。你有什么建议吗?我也需要做到这一点。我正在考虑制作一个散列访问者,该访问者特别知道在 ConstantExpressions 的基础值上包含和调用 GetHashCode。你怎么看?
    • 我的理解是它是表达式树的全文,例如,这是我通过带有 where 子句和投影.....value(Quest.Intersect. Core.DataHubQueryableTable1[Quest.Intersect.TestHarness.Customer]).Where(cust => (cust.LastName = "jarvis")).Select(cust => new <>f__AnonymousType12(CompID = cust.CompanyID, LastName = cust.LastName))
    • 正如你所看到的,它包含评估的常量加上匿名类等。在我看来,这个的哈希值在字典中是一个足够好的键......但是,话虽如此,替代方案将如您所建议的那样,创建一个访问者,该访问者创建每个节点/叶子的复合哈希
    猜你喜欢
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多