如何在Linq中使用Where运算符

时间:2011-01-22 11:50:55

标签: c# linq

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

但为什么当我使用数字而不是参数时它可以正常工作?

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

我想知道是否有办法在Linq中实现此代码,因为它给了我一个错误。
谢谢。

4 个答案:

答案 0 :(得分:2)

您需要更具体地了解实际获得的错误,但是,作为一般指南,如果FunctionOn无法转换为数据库特定语言查询(如果SomeObject是数据库实体),则通常会失败或者它不返回Where函数所期望的布尔值。

答案 1 :(得分:2)

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

您说SomeObjectIQueryable。这让我怀疑你没有查询内存中的集合(LINQ-to-Objects),你的查询应该没有任何问题地成功,但你可能会查询更“动态”的东西。为了演示这个问题,我假设我们在这里处理LINQ-to-SQL ......但是这个假设并不一定适用于我想在下面解释的内容:

  

更新:您刚才在评论中说过您正在使用LINQ-to-MongoDB,因此以下内容适用于您的问题。

使用LINQ-to-SQL之类的东西,查询的问题不是FunctionOn谓词方法的问题,或者是它与Where运算符组合的方式。手头的问题是LINQ-to-SQL(或者你正在使用的任何LINQ提供程序)无法识别你的方法。它试图在运行时将LINQ表达式转换为SQL查询(毕竟这正是IQueryable最适合的!),但它不知道如何将FunctionOn转换为SQL。 / p>

如果LINQ-to-SQL要实现这一点,就必须弄清楚你的方法在做什么,然后找到一种方法来表达它作为有效的SQL。这将需要很多复杂性和智慧。例如,它必须检查您的方法,例如通过反编译,然后将其重新编译为SQL。这显然不适用于任何任意复杂的方法。想象一下,您的FunctionOn方法包含对Debug.WriteLine的调用。这无法将其转换为SQL查询。

因此,LINQ-to-SQL仅限于一些知道如何处理的情况和表达式。如果遇到LINQ表达式中的任何其他内容,它会让你知道它不知道如何处理FunctionOn(即如何将其转换为SQL),例如,“方法不支持FunctionOn。“

将查询编写为:

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

一切都应该可以正常工作,因为LINQ-to-SQL知道如何将p.I == 1转换为SQL WHERE子句中的相应等式测试。

答案 2 :(得分:0)

这可能有效,请尝试:

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

它也适用于Linq-To-Entities和Linq-To-SQL!

为什么!怎么样?

因为像 stakx 那样解释。 IQueryable存储您的表达式。如果您查看docs for IQueryable它有Expression属性,则此存储您在代码中编写的Linq,然后LinqProvider会将其转换为正确的内容,您的情况是 MongoDB语法/ SQL IDK?对于linq-to-sql,这将转变为T-SQL表达式。所以没有 SQL-way 来编写FunctionOn()。可以用SQL神奇地调用用C#编写的函数吗?都能跟得上!

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

就像@Will对评论的正确说法一样,这会将每个对象带入内存然后进行查询。有时候它可能不是你想要做的,但是我希望你理解为什么你的代码不起作用,如果你需要那么有一个解决方法

希望它能给你几周前在观看很多9频道Linq视频时发现的相同见解。 =)

答案 3 :(得分: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; }
}