C# 如何使用linq表达式过滤数据库中的记录?

C# 如何使用linq表达式过滤数据库中的记录?,c#,.net,linq,lambda,expression,C#,.net,Linq,Lambda,Expression,我正在努力实现以下模式: Main() { ... GetFilteredUsersById(u => u >= 100 && u < 200).Dump(); .... } public List<UserRecord> FilteredUsersById(Func<int, bool> filter) { Expression<Func<UserRecord, bool>> f

我正在努力实现以下模式:

Main()
{
    ...
    GetFilteredUsersById(u => u >= 100 && u < 200).Dump();
    ....
}

public List<UserRecord> FilteredUsersById(Func<int, bool> filter)
{
    Expression<Func<UserRecord, bool>> filterExpression = x => filter(x.Id);
    return someUserRecordsDb.Where(filterExpression).ToList();
}

public class UserRecord
{
    public int Id;

    public string Name;
}
Main()
{
...
getFilteredUserById(u=>u>=100&&u<200).Dump();
....
}
公共列表过滤器REDUSERSBYID(Func过滤器)
{
表达式filtereexpression=x=>filter(x.Id);
返回someUserRecordsDb.Where(filterExpression.ToList();
}
公共类用户记录
{
公共int Id;
公共字符串名称;
}
当然,这是失败的

NotSupportedException:方法“System.Object DynamicInvoke(System.Object[])”不支持到SQL的转换

我理解错误发生的原因,但不知道如何修复它

下面是一个确实有效的模式,但我想了解需要对上面第一个模式的代码进行哪些更改才能使其有效

Main()
{
    ...
    GetFilteredUsersById(u => u.Id >= 100 && u.Id < 200).Dump();
    ....
}

public List<UserRecord> FilteredUsers(Expression<Func<UserRecord, bool>> filter)
{
    return someUserRecordsDb.Where(filter).ToList();
}

public class UserRecord
{
    public int Id;

    public string Name;
}
Main()
{
...
getFilteredUserById(u=>u.Id>=100&&u.Id<200).Dump();
....
}
公共列表过滤器过滤器(表达式过滤器)
{
返回someUserRecordsDb.Where(filter.ToList();
}
公共类用户记录
{
公共int Id;
公共字符串名称;
}

感谢您在StackOverflow回答我的第一个问题

如您所知,LINQ to SQL的工作原理是将lambda作为表达式树而不是委托。然后,它分析这些树并尝试生成等效的SQL代码。显然,它不能支持所有可以用C#编写的东西

在第二个代码段中,LINQ提供程序看到一个表达式树,其中包含以下内容:

u => u.Id >= 100 && u.Id < 200
这是非常不同的,因为它是对提供者不知道的任意方法的调用。因此,现在提供者必须查看该方法的内部,并查看它包含的内容。如果该方法具有另一级别的间接寻址,则提供程序必须进一步查看。等等

如果表达式树需要这种工作,则提供程序将拒绝这样做。因此,对任意方法的任何调用都会失败,这是可以理解的


因此,答案很简单:不要在创建表达式树的位置和要转换为SQL的实际表达式之间设置间接级别,否则LINQ提供程序将完全拒绝它。

这里需要记住两件事

1。表达式与函数的比较

您需要了解的主要内容之一是
表达式
Func
或任何类型的委托类型之间的区别。简言之,表达式传递的是lamda的树表示形式,可以将其转换为Sql

这里有一个很好的答案可以深入讨论这一点:

2。并非所有表达式都能与Linq to Sql一起使用

即使函数可以表示为表达式,也不意味着对于使用linq表达式的提供程序,lambda表达式中执行的操作将有一个正确的映射

这就是为什么会出现异常:

NotSupportedException:方法“System.Object DynamicInvoke(System.Object[])”不支持到SQL的转换

这里,即使它是一个有效的表达式,也无法将操作转换为sql,这就是为什么会出现异常,即使
filter
如果作为表达式传递并直接调用,将是一个有效的lambda。语句的翻译是,它试图调用此func
filter
,它不直接映射到sql中的任何内容

您无法使第一个示例正常工作。想想看——LINQ代码如何知道任意
Func过滤器在运行时包含什么?它必须反编译实际的IL才能将其转换为SQL!第二个代码的工作原理正是因为该代码没有编译为IL,而是作为表达式树传递,可以在执行之前将其转换为SQL。
x => filter(x.Id)