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中实现此代码,因为它给了我一个错误。
谢谢。
答案 0 :(得分:2)
您需要更具体地了解实际获得的错误,但是,作为一般指南,如果FunctionOn
无法转换为数据库特定语言查询(如果SomeObject是数据库实体),则通常会失败或者它不返回Where
函数所期望的布尔值。
答案 1 :(得分:2)
SomeObject.Where(p => FunctionOn(p.I));
您说SomeObject
是IQueryable
。这让我怀疑你没有查询内存中的集合(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; }
}