c#lambda,内部变量用于预先计算

时间:2015-04-14 09:37:57

标签: c# entity-framework lambda func

我有一个带有过滤lambda表达式的实体框架应用程序,如下所示:

x => x.Where(pn => pn.Product.Evaluation.Any(ee => ee.EvaluationToDocuments.Any(e2d => e2d.Document.SpiderFailedCheckCount != null))) 事实证明这是非常缓慢的,反过来要快得多,即找到正确的EvaluationToDocuments,并通过评估选择他们的产品。

所以我做了一个预先计算: spiderFailedCheckCountProductIds = _context.EvaluationToDocuments.Where(e2d => e2d.Document.SpiderFailedCheckCount != null).Select(e2d => e2d.Evaluation.ProductID).Distinct().OrderBy(p => p).ToList();

然后我的第一个表达式可以这样做: x => x.Where(pn => spiderFailedCheckCountProductIds.Contains(pn.ProductID))

它可能更快,但速度足够快,比第一个版本快很多。

一般来说,函数中局部变量的目的是避免多次进行昂贵的计算。这可以用lambda表达式完成吗?类似于(x) => var a = x+5, a*4(不是最好的例子)

我想避免编写普通函数,并将这些过滤函数保留为对象。

1 个答案:

答案 0 :(得分:1)

let clause(来自MSDN的示例):

var earlyBirdQuery =
    from sentence in strings
    let words = sentence.Split(' ')
    from word in words
    let w = word.ToLower()
    where w[0] == 'a' || w[0] == 'e'
        || w[0] == 'i' || w[0] == 'o'
        || w[0] == 'u'
    select word;

但请注意,您的问题是另一个问题:查询生成的SQL查询计划非常糟糕。您通过对SQL执行两个单独的查询来解决这个问题。也许您甚至可以将两个查询合并在一起并在单个"批处理"中进行。

SQL Server通常已经缓存了相同的子表达式。如果你在查询中执行MAX(某事)的两倍,那么SQL不可能执行两次。它会注意到它可以重用结果并重用它。

SELECT MAX(id), MAX(id) FROM Foo

或者如果你这样做

SELECT SUBSTRING(name, 1, 5) FROM Foo WHERE SUBSTRING(name, 1, 5) = 'Hello'

可能SUBSTRING每行只构建一次。