我看过其他与此相似的问题,但我找不到任何可行的答案.
我一直使用以下代码来生成唯一的密钥,用于将我的LINQ查询的结果存储到缓存中.
string key = ((LambdaExpression)expression).Body.ToString(); foreach (ParameterExpression param in expression.Parameters) { string name = param.Name; string typeName = param.Type.Name; key = key.Replace(name + ".",typeName + "."); } return key;
对于包含整数或布尔值的简单查询,似乎可以正常工作,但是当我的查询包含嵌套常量表达式
// Get all the crops on a farm where the slug matches the given slug. (x => x.Crops.Any(y => slug == y.Slug) && x.Deleted == false)
所返回的关键是:
(True AndAlso (Farm.Crops.Any(y =>
(value(OzFarmGuide.Controllers.FarmController+<>c__DisplayClassd).slug
== y.Slug)) AndAlso (Farm.Deleted == False)))
正如你可以看到我通过的任何作物名称将给出相同的关键结果.有没有办法可以提取给定参数的值,以便区分我的查询?
还要转换y来说正确的类型名称会很好…..
解决方法
正如Polity和Marc在他们的评论中所说的,你需要的是LINQ表达式的部分评估者.您可以在
Matt Warren’s LINQ: Building an IQueryable Provider – Part III中阅读使用
ExpressionVisitor
的方法.文章
Caching the results of LINQ queries by Pete Montgomery(由Polity链接)介绍了有关这种缓存的一些更多细节,例如如何在查询中表示集合.
另外,我不知道我会依靠这样的ToString().我认为这主要是为了调试目的,未来可能会改变.另一种方法是创建自己的IEqualityComparer< Expression>这可以为任何表达式创建一个哈希码,并且可以比较两个表达式的相等性.我也可能会使用ExpressionVisitor,但这样做将是相当乏味的.