在下面的代码中,当我直接在查询中放入“dl.DamageCount> 5”或将“dl.DamageCount> 5”移动到某个方法或函数,然后从查询中调用它时,有什么不同吗?
似乎当我将其移动到方法中时,查询无法正常工作。实际上,无论条件评估如何,函数/方法似乎总是返回true。我正在使用Linq-to-NHibernate。
var q = from dl in session.Linq<DamageList>()
where
dl.DamageCount > 5
答案 0 :(得分:4)
您可以做的最好的事情是在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?
您可以使用&amp;&amp ;;编写复合谓词。 oerator仍然在表达式中捕获它:
Expression<Func<DamageList, bool>> predicate =
dl => dl.DamageCount > 5 && dl.Name.Contains(criteria);
你问在这样的表达式中调用方法 - 好吧,那个例子确实调用了一个方法!
它构建了各种类型的Expression
个节点的树。某处包含一个方法调用节点,它表示调用Contains
的{{1}}方法(假设string
是Name
)。所以这是嵌入在表达式中的方法调用指令的示例。为了使其工作,Linq提供程序必须知道该方法的作用,因此它可以将其转换为等效的SQL(就像典型的ORM系统一样)。
因此,您可以在表达式中嵌入某些标准方法调用 - 它需要Linq提供程序了解它们。 string
的方法定义明确,但并非每个提供者都必须能够处理所有这些方法。
Linq提供程序不可能允许您添加自己的扩展来处理额外的方法,但我不知道任何支持(显然如果系统是开源的,您可以添加您的自己的)。
总结一下 - Linq提供程序需要一个表达式节点树,它可以分析它以转换为其他语言(如SQL),以便在另一个上下文(如远程数据库内)中执行。如果编写普通方法,C#编译器会将它们编译为低级可执行IL,而不是表达式节点。所以这就像一个死胡同:没有内置的工具可以将IL转回表达式节点。