如何将Predicate <t>传递给Linq to SQL中的Where()方法?</t>

时间:2010-11-11 16:41:29

标签: linq linq-to-sql expression predicate

我有以下型号:

 +--------+
 | Folder |
 +--------+
     | 1
     |
     | *
+----------+         +---------+
| WorkItem |---------| Project |
+----------+ *     1 +---------+

我需要检索具有当前WorkItems数量的文件夹列表。

如果我已经指定了一个项目,那么我只想要每个文件夹中与指定项目相关联的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);

构建,但随后失败,'用于查询运算符的不支持的重载'在哪里'。'

我将需要向IWorkItemCriteria接口添加其他属性,因此能够动态构建可由Linq干净地转换为SQL的谓词非常重要。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我抓住了MSDN的一些东西:我的想法是你只需将其指向现有的功能:

使用System;

公共类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))

但我不确定。不过,我很确定你需要“新”,希望这有助于:)

答案 1 :(得分:1)

我认为你的问题是你想从第二个表达式(传递给results.Where.Select())中引用一个表达式(过滤器),并且LINQ to SQL IQueryable提供者没有'我知道如何吸引它的价值。

您需要做的是从头开始编写Select表达式,以便内联表达您的动态过滤器。对于匿名类型,这可能会更加困难,我不确定。我刚刚发现了以下文章,似乎很好地解释了这一点:http://www.codeproject.com/KB/linq/rewrite_linq_expressions2.aspx