代码之家  ›  专栏  ›  技术社区  ›  Nathan

作为常量的预编译Lambda表达式树转换?

  •  4
  • Nathan  · 技术社区  · 15 年前

    this question this question ,我怀疑Linq2Sql也做了类似的事情)。

    在许多情况下,甚至大多数情况下,表达式树转换总是相同的,即如果我有一个函数

    public string GenerateSomeSql(Expression<Func<TResult, TProperty>> expression)
    

    那么任何具有相同参数的调用都将始终返回相同的结果,例如:

    GenerateSomeSql(x => x.Age)  //suppose this will always return "select Age from Person"
    GenerateSomeSql(x => x.Ssn)  //suppose this will always return "select Ssn from Person"
    

    因此,本质上,具有特定参数的函数调用实际上只是一个常量,只是在运行时不断地重新计算它会浪费时间。

    编辑

    2 回复  |  直到 8 年前
        1
  •  3
  •   Nathan Baulch    15 年前

    优秀的 LINQ IQueryable Toolkit ExpressionComparer 类,该类遍历两个表达式的层次结构并确定它们是否相等。此技术还用于收集对常用属性的引用,以便进行参数化和删除冗余联接。

    您的方法将如下所示:

    private readonly IDictionary<Expression, string> _cache
        = new Dictionary<Expression, string>(new ExpressionEqualityComparer());
    
    public string GenerateSomeSql(Expression<Func<TResult, TProperty>> expression)
    {
        string sql;
        if (!_cache.TryGetValue(expression, out sql))
        {
            //process expression
            _cache.Add(expression, sql);
        }
        return sql;
    }
    
    class ExpressionEqualityComparer : IEqualityComparer<Expression>
    {
        public bool Equals(Expression x, Expression y)
        {
            return ExpressionComparer.AreEqual(x, y);
        }
    
        public int GetHashCode(Expression obj)
        {
            return ExpressionHasher.GetHash(obj);
        }
    }
    
        2
  •  1
  •   John Bledsoe    15 年前

    首先,我怀疑你关于编译表达式导致性能下降的假设在现实中是行不通的。我的经验表明,在常规的“好”代码导致问题之前,还有很多因素(数据库访问、网络延迟、非常差的算法)会导致性能瓶颈。过早的优化是万恶之源,所以构建应用程序并运行压力测试来发现实际的性能瓶颈,因为它们通常不是您所期望的。

    尽管如此,我认为预编译取决于表达式被转换成什么。我知道使用linqtosql可以调用 DataContext.GetCommand(Expression) 找到一个 DBCommand

    推荐文章