【发布时间】:2009-04-17 00:17:33
【问题描述】:
我正在努力将一些伪智能缓存构建到 LINQ query provider 中。我想做的(理想情况下)是在某些情况下使用给定查询的表达式树作为缓存键。但是,我不想存储整个对象图本身,那么从表达式树中获取类似哈希和的值的快速方法是什么?或者如果我走错了方向,还有更好的选择吗?
【问题讨论】:
标签: .net linq expression-trees
我正在努力将一些伪智能缓存构建到 LINQ query provider 中。我想做的(理想情况下)是在某些情况下使用给定查询的表达式树作为缓存键。但是,我不想存储整个对象图本身,那么从表达式树中获取类似哈希和的值的快速方法是什么?或者如果我走错了方向,还有更好的选择吗?
【问题讨论】:
标签: .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* accumulate( children.begin(), children.end(), *OP* );
当然,这与我们用来评估表达式树的递归相同(期望我们调用node.eval( children);)
【讨论】:
您可能可以使用此处提供的代码来完成此操作。 http://petemontgomery.wordpress.com/2008/08/07/caching-the-results-of-linq-queries/
这展示了如何解决闭包问题并支持本地集合。
【讨论】:
.ToString()。
嗯,实际上我认为这可能很简单。
Expression 对象的 ToString() 方法将为您提供 Expression 的文本表示,如果您只想评估键的等效性,您可以对其进行哈希处理。
【讨论】:
1[Quest.Intersect.TestHarness.Customer]).Where(cust => (cust.LastName = "jarvis")).Select(cust => new <>f__AnonymousType12(CompID = cust.CompanyID, LastName = cust.LastName))