2010-02-21 22 views
2

在下面的代码中,当我将“dl.DamageCount> 5”直接放入查询中,或者将“dl.DamageCount> 5”移动到某个方法或函数然后从查询中调用时,它有什么区别?是否有必要不使用LINQ查询中的方法?

看来,当我将它移入一个方法,查询无法正常工作。事实上,无论条件评估如何,函数/方法总是返回true。我正在使用Linq-to-NHibernate。

var q = from dl in session.Linq<DamageList>() 
      where 
      dl.DamageCount > 5 

回答

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?

您可以使用& & oerator写一个复合谓语,仍然捕捉它在表达式:

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

你问过在这样一个表达式中调用方法 - 那么这个例子确实调用了一个方法!

它建立了Expression各种类型的节点树。包括某处将会有一个方法调用节点,该节点表示调用方法string(假设Namestring)。所以这是嵌入表达式中的方法调用指令的一个例子。为了使其发挥作用,Linq提供者必须知道该方法的作用,因此它可以将其转换为等效的SQL(就像典型的ORM系统那样)。

因此,您可以在表达式中嵌入某些标准方法调用 - 它需要Linq提供者了解它们。 string的方法是明确的,但不是每个提供者都必须能够处理所有这些方法。

Linq提供程序不允许你添加自己的扩展来处理额外的方法,但我不知道有任何支持(显然如果系统是开源的,你可以添加你自己)。总结 - Linq提供者需要一个表达式节点树,它可以分析转换成其他语言(如SQL),以便在另一个环境(如远程数据库内)中执行。如果您编写普通方法,C#编译器会将它们编译为低级可执行文件IL,而不是表达式节点。所以这就像一个死胡同:没有内置的设备可以将IL转换回表达式节点。

+0

那么我有多个条件呢?例如:其中dl.DamageCount> 5 && dl.Name.Contains(条件) – 2010-02-21 11:40:51

+0

查看已添加的文本... – 2010-02-21 11:50:49

+0

亲爱的Earwicker,另外一个问题:是否可以用这个表达式调用另一个方法?我的意思是:Expression > predicate = MyFunc(); – 2010-02-21 11:54:58

相关问题