Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 对表达式树进行散列_.net_Linq_Expression Trees - Fatal编程技术网

.net 对表达式树进行散列

.net 对表达式树进行散列,.net,linq,expression-trees,.net,Linq,Expression Trees,我正在将一些伪智能缓存构建到数据库中。在某些情况下,我希望(理想情况下)使用给定查询的表达式树作为缓存键。但是,我不想存储整个对象图本身,那么从表达式树中获取类似哈希和的值的快速方法是什么呢?或者如果我走错了方向,还有更好的选择吗?让我们考虑一下。您可能希望将(表达式树的哈希、结果)存储在映射中 如果不存储整个树,就无法区分相同的树和哈希冲突 根据定义,散列将一个较大的集合映射到一个较小的集合(这就是散列有用的原因),因此根据定义,您将有(至少有可能)冲突 当您得到表达式树时,您将对其进行哈希运

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

让我们考虑一下。您可能希望将(表达式树的哈希、结果)存储在映射中

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

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

当您得到表达式树时,您将对其进行哈希运算,然后在映射中查找结果,这将导致两种可能性:

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

  • 它是映射中的一个散列,但由于没有在映射中存储生成散列的旧表达式树,因此无法将新传递的表达式与旧表达式进行比较。你可能有一个匹配或者你可能有一个碰撞,但是没有办法区分这两种可能性。无法返回缓存的结果,因为它可能是冲突

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

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

    hashATree:
    if leaf node
      return hash(node)
    else
      return hash(node) *OP* hashATree(left.child) *OP* hashATree(right.child)
    
    其中OP是某种运算(可能是乘法),或者更一般地说是
    hash(node)*OP*累加(children.begin()、children.end()、*OP*)


    当然,这是我们用来计算表达式树的相同递归(除了我们调用
    node.eval(children);

    嗯,实际上我认为这可能非常简单


    Expression对象的ToString()方法将为您提供表达式的文本表示,如果您只想计算一个键的等价性,您可以对其进行哈希运算。

    您可能可以使用此处提供的代码来完成此操作。


    这说明了如何解决闭包问题,并支持本地集合。

    吹毛求疵,散列并不总是从一个大集合到一个小集合,例如完美散列。你关于冲突的观点在理论上是正确的,但实际上也不相关。MD5和SHA也有可能发生碰撞,但我们仍然使用它们,因为它们是实用的。我需要一个实用的散列,而不是数学上防冲突的散列。为了回答您关于备份存储同步问题的问题,我已经解决了这些问题。然而,我觉得用我目前的方法为缓存设置关键帧(存储表达式树本身)进行生产并不舒服。这并没有包含表达式树的完整哈希……而且许多表达式树都有相同的字符串值,但有不同的底层节点。你有什么建议吗?我也需要做到这一点。我正在考虑创建一个hash访问者,它专门知道在ConstantExpressions的底层值上包含并调用GetHashCode。你认为呢?我的理解是它是表达式树的全文,例如,这是我通过带有where子句和投影的查询得到的…..值(Quest.Intersect.Core.DataHubQueryableTable
    1[Quest.Intersect.TestHarness.Customer])。其中(cust=>(cust.LastName=“jarvis”)。选择(客户=>新f_u匿名类型1
    2(CompID=cust.CompanyID,LastName=cust.LastName))正如你所看到的,它包含了已计算的常量和匿名类等。在我看来,这个散列在字典中是一个足够好的键……然而,正如你所建议的,另一个选择是创建一个访问者,它创建了每个节点/叶的复合散列。如果你可以在这里包含相关的位,那就是太好了。人们来这里是为了得到答案,而不是链接……除非你能保证你的博客永远存在,否则如果它掉下去,这个答案将变得毫无用处。他基本上使用
    .ToString()