2011-01-22 43 views
1
SomeObject.Where(p => FunctionOn(p.I)); 
<<>> 
public bool FunctionOn(int i){ 
    return (i == 1);} 
<<>> 
error message : The method FunctionOn is not supported 

,但为什么当我使用的,而不是参数号能正常工作?
如何使用Where运算符Linq中

SomeObject.Where(p => FunctionOn(1)); 

我想知道是否有实现Linq中的这段代码的方式,因为它给了我一个错误。
谢谢。

+0

你什么错误? `FunctionOn`应该返回`bool`。 – 2011-01-22 11:53:03

+0

是的,像这种方法的错误不支持或类似的东西。 (我无法使用它) – Rawhi 2011-01-22 11:54:35

+0

编译错误或运行时异常? – Elisha 2011-01-22 11:55:58

回答

2
SomeObject.Where(p => FunctionOn(p.I)); 

你说SomeObjectIQueryable。这让我怀疑你没有查询内存中的集合(LINQ到对象),查询应该可以在没有任何问题的情况下成功,但是你可能会查询更多的“动态”内容。为了展示问题的缘故,我认为我们在这里处理LINQ到SQL ...但这种假设并不一定是必然为真什么,我想下面的解释:

更新:你刚刚在您使用LINQ到MongoDB的评论说,所以下面应该适用于您的问题。

的东西像LINQ到SQL与您的查询的问题不在于什么是错与FunctionOn判断方法,或者你用Where操作相结合的方式。现在的问题在于,LINQ-to-SQL(或者您正在使用的任何LINQ提供程序)无法识别您的方法。它尝试将LINQ表达式转换为在运行SQL查询(这正是IQueryable是好的,毕竟!),但它不知道如何将转换FunctionOn到SQL。

如果LINQ到SQL为实现这一目标,就必须弄清楚你的方法做,然后找到一种方式来表达,作为有效的SQL。这需要很多复杂和智慧。例如,它必须检查你的方法,例如通过反编译,然后重新编译为SQL。这显然不适用于任何复杂的方法。假设您的FunctionOn方法包含对Debug.WriteLine的调用。没有办法将其转换为SQL查询。

因此LINQ到SQL仅限于少数病例和表情,它知道如何处理。如果遇到任何其他的LINQ表达式,它会让你知道,它不知道如何处理FunctionOn(即如何将其转换为SQL)说像,“的方法功能特征不被支持。 “

一旦你写你的查询为:

SomeObject.Where(p => p.I == 1); 

一切都应该很好地工作,因为LINQ到SQL知道如何翻译你的p.I == 1到SQL WHERE条款相应的相等测试。

2

您需要更具体和你实际上得到,然而,作为一般指导错误,通常这会失败,如果FunctionOn不能被翻译成特定数据库语言查询(如果SomeObject是DB实体)或它不返回Where函数期望的布尔值。

0

这可能会实现,试试:

SomeObject.AsEnumerable().Where(p => FunctionOn(p.I)) 

它将对LINQ到实体和LINQ到SQL工作过!

为什么!怎么样?

因为像stakx解释。 IQueryable存储您的表情。如果你看看它有一个Expression属性,你在你的代码编写,然后LinqProvider然后将其转化为正确的事情,你的情况,这将是MongoDB的语法/ SQL IDK的docs for IQueryable,这 LINQ的?对于linq-to-sql,这将变成一个T-SQL表达式。所以没有的SQL方式FunctionOn()。它可以神奇地调用你用C#编写的SQL函数吗?不!现在

IEnumerable是内存中的对象集合。当你说AsEnumerable()时,你得到内存中的对象,那么当你做时Where(x=> func(x)) Linq-To-Objects可以处理它没问题。

像@Will上的评论正确地说,这得到每一个对象到内存,然后查询它。有时,它可能不是你想要做什么,但我希望你能理解为什么代码不工作,如果你还需要是八九不离十一个解决方法

希望它可以给你的我几周前在观看很多channel9 Linq视频时发现了同样的见解。 =)

0

正如其他人提及的,你的FunctionOn方法没有由数据源直接平移。

但是,可能有变通的办法 - 大你正在做一个比较,这取决于你需要做什么样的比较,以及如何。

相反,如果你创建一个扩展方法,这需要一个IQueryable<T>并返回IQueryable<T>你可以直接写你的表达。

这可以让您重新使用复杂的表达式。您还应该能够与参考数据列表进行比较 - 但是您需要注意,此比较列表不会超过数据源允许的参数。

例子:

static void Main(string[] args) 
{ 


    var data = new List<Customer> 
       { 
        new Customer {Id = 1, Name = "Anna"}, 
        new Customer {Id = 2, Name = "Bob"}, 
        new Customer {Id = 3, Name = "Claire"} 
       }; 



    var result = data.AsQueryable().TestCustomer(); 




} 

private static IQueryable<Customer> TestCustomer(this IQueryable<Customer> source) 
{ 
    return source.Where(x => x.Id > 1); 
} 


public class Customer 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
}