【问题标题】:How can I pass a Predicate<T> to the Where() method in Linq to SQL?如何将 Predicate<T> 传递给 Linq to SQL 中的 Where() 方法?
【发布时间】: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&lt;TSource&gt; (System.Collections.Generic.IEnumerable&lt;TSource&gt;, System.Func&lt;TSource,bool&gt;)' 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 的谓词的能力非常重要。

有什么想法吗?

【问题讨论】:

    标签: linq linq-to-sql expression predicate


    【解决方案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))
      

      但我不确定。再说了,我很确定你需要“新”,希望这会有所帮助:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多