如何将 Predicate<T> 传递给 Linq to SQL 中的 Where() 方法?
Posted
技术标签:
【中文标题】如何将 Predicate<T> 传递给 Linq to SQL 中的 Where() 方法?【英文标题】:How can I pass a Predicate<T> to the Where() method in Linq to SQL? 【发布时间】:2010-11-11 16:41:29 【问题描述】:我有以下型号:
+--------+
| Folder |
+--------+
| 1
|
| *
+----------+ +---------+
| WorkItem |---------| Project |
+----------+ * 1 +---------+
我需要检索具有当前 WorkItems 计数的文件夹列表。
如果我指定了一个项目,那么我只需要每个文件夹中与指定项目关联的工作项的计数。
如果没有指定 Project,它应该返回 WorkItem 总数。
我有以下 Linq to SQL 代码:
public interface IWorkItemCriteria
int? ProjectId get;
public static IQueryable<Folder> GetFoldersWithItemCounts(IWorkItemCriteria criteria)
var results = from folder in dataContext.Folders
select new
Folder = folder,
Count = folder.WorkItems.Count()
;
return(results);
问题是 - 我想过滤正在计数的工作项。
这行得通:
var results = from folder in dataContext.Folders
select new
Folder = folder,
Count = folder.WorkItems.Where(item => item.ProjectId == criteria.ProjectId).Count()
;
但我无法让它使用任何类型的动态谓词/表达式。我尝试使用的语法是:
var results = from folder in dataContext.Folders
select new
Folder = folder,
Count = folder.WorkItems.Where(filter).Count()
;
我试过了
Predicate<WorkItem> filter = (item => item.ProjectId == criteria.ProjectId);
和
Expression<Func<WorkItem, bool>> filter = (item => item.ProjectId == criteria.ProjectId)
两者都不会编译 - 给出The type arguments for method 'System.Linq.Enumerable.Where<TSource> (System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
我试过了
Func<WorkItem, bool> filter = (item => item.ProjectId == criteria.ProjectId);
构建,但随后因“用于查询运算符 'Where' 的不支持重载而失败。”
我将需要向 IWorkItemCriteria 接口添加额外的属性,因此动态构造可以被 Linq 干净地转换为 SQL 的谓词的能力非常重要。
有什么想法吗?
【问题讨论】:
【参考方案1】:我认为您的问题是您想从第二个表达式(传递给 results.Where.Select() 的表达式)中引用一个表达式(过滤器),而 LINQ to SQL IQueryable 提供程序没有不知道如何获得它的价值。
您需要做的是从头开始编写 Select 表达式,以便内联作为您的动态过滤器的表达式。对于匿名类型,这可能会更加困难,我不确定。刚找到下面这篇文章,好像解释的很好:http://www.codeproject.com/KB/linq/rewrite_linq_expressions2.aspx
【讨论】:
【参考方案2】:我从 MSDN 中得到的东西:这个想法是你只需将它指向一个现有的函数:
使用系统;
公共类 GenericFunc
public static void Main()
Func<string, string> convertMethod = UppercaseString;
private static string UppercaseString(string inputString)
return inputString.ToUpper();
我相信还有其他方法。我记得做过类似的事情
new Func<WorkItem, bool>((item => item.projectId == criteria.ProjectId))
但我不确定。再说了,我很确定你需要“新”,希望这会有所帮助:)
【讨论】:
以上是关于如何将 Predicate<T> 传递给 Linq to SQL 中的 Where() 方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何有条件地替换Collection中的值,例如replaceIf(Predicate<T>)?
为啥 Java 8 的 Predicate<T> 不扩展 Function<T, Boolean>
IEnumerable<T>.Contains with predicate