代码之家  ›  专栏  ›  技术社区  ›  Afshar Mohebi

是否有必要在LINQ查询中不使用方法?

  •  2
  • Afshar Mohebi  · 技术社区  · 14 年前

    在下面的代码中,当我将“dl.damagecount>5”直接放到查询中,或者当我将“dl.damagecount>5”移到方法或函数中,然后从查询中调用它时,有什么不同吗?

    当我将它移到方法中时,查询似乎不能正常工作。实际上,不管条件如何评估,函数/方法似乎总是返回true。我用LINQ来氨气。

     var q = from dl in session.Linq<DamageList>()
                where
                dl.DamageCount > 5
    
    1 回复  |  直到 14 年前
        1
  •  4
  •   Community WizardZ    7 年前

    最好的方法是在 Expression<> . 一个方法已经编译到IL,因此不能被Linq提供程序分离。

    Expression<Func<DamageList, bool>> predicate = item => item.DamageCount > 5;
    

    然后可以将该谓词直接传递给 Where :

    var q = session.Linq<DamageList>().Where(predicate);
    

    如果要动态组合两个这样的表达式,可以将这两个表达式的代码都写入一个表达式,也可以在单独的表达式中捕获这两个表达式。这变得很复杂,因为您需要每个引用 item 被传进来。这是一个完全不同的问题,已经被问到: How do I dynamically create an Expression<Func<MyClass, bool>> predicate?

    您可以使用&oerator编写复合谓词,并将其捕获到表达式中:

    Expression<Func<DamageList, bool>> predicate = 
        dl => dl.DamageCount > 5 && dl.Name.Contains(criteria);
    

    你问过如何在这样的表达式中调用方法——好吧,那个例子确实调用了一个方法!

    它建造了一棵树 Expression 各种类型的节点。其中的某个地方将包含一个方法调用节点,该节点表示调用 Contains 方法 string (假设) Name 是一个 一串 )这是一个嵌入在表达式中的方法调用指令的例子。为了实现这一点,LINQ提供程序必须知道该方法的作用,因此它可以将其转换为等效的SQL(对于典型的ORM系统也是如此)。

    因此,您可以在表达式中嵌入某些标准方法调用-它要求LINQ提供程序了解它们。方法 一串 定义良好,但并非每个提供者都必须能够处理所有这些问题。

    Linq提供者不可能允许您添加自己的扩展来处理额外的方法,但是我不知道有任何支持这一点(显然,如果系统是开源的,您可以添加自己的扩展)。

    概括地说,LINQ提供程序需要一个表达式节点树,它可以分析该树,将其转换为其他语言(如SQL),以便在其他上下文(如远程数据库内部)中执行。如果您编写普通的方法,C编译器将把它们编译成低级别的可执行IL,而不是表达式节点。所以这就像一个死胡同:没有内置的工具可以将IL转换回表达式节点。