我如何传递谓词Linq to SQL 中的Where() 方法?

发布于 2024-10-02 02:32:48 字数 2000 浏览 9 评论 0原文

我有以下模型:

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

我需要检索具有当前工作项计数的文件夹列表。

如果我指定了一个项目,那么我只需要每个文件夹中与指定项目关联的工作项的计数。

如果未指定项目,则应返回工作项总数。

我有以下 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 argument for method 'System.Linq.Enumerable.Where; (System.Collections.Generic.IEnumerable, System.Func)' 无法从用法中推断出来。尝试显式指定类型参数。

我已经尝试过

Func<WorkItem, bool> filter = (item => item.ProjectId == criteria.ProjectId);

构建,但随后失败,并显示“查询运算符‘Where’使用的重载不受支持。”

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

有什么想法吗?

I have the following model:

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

I need to retrieve a list of Folders with the current count of WorkItems.

If I have specified a Project, then I only want the count of WorkItems in each Folder that are associated with the specified Project.

If no Project is specified, it should return the total WorkItem count.

I have the following Linq to SQL code:

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);
}

The problem is - I want to filter the work items that are being counted.

This works:

    var results = from folder in dataContext.Folders
        select new {
              Folder = folder,
              Count = folder.WorkItems.Where(item => item.ProjectId == criteria.ProjectId).Count()
    };

but I can't get it to use any kind of dynamic predicate / expression. The syntax I'm trying to use is:

    var results = from folder in dataContext.Folders
        select new {
              Folder = folder,
              Count = folder.WorkItems.Where(filter).Count()
    };

I've tried

Predicate<WorkItem> filter = (item => item.ProjectId == criteria.ProjectId);

and

Expression<Func<WorkItem, bool>> filter = (item => item.ProjectId == criteria.ProjectId)

neither of which will compile - gives 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.

I've tried

Func<WorkItem, bool> filter = (item => item.ProjectId == criteria.ProjectId);

which builds, but then fails with 'Unsupported overload used for query operator 'Where'.'

I'm going to need to add additional properties to the IWorkItemCriteria interface, so the ability to dynamically construct a predicate that can be cleanly translated by Linq to SQL is pretty important.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半透明的墙 2024-10-09 02:32:48

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

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

I think your problem is that you'd like to reference one expression (filter) from within a second expression (the one being passed to results.Where.Select()), and that the LINQ to SQL IQueryable provider doesn't know how to pull in the value of that.

What you're going to have to do is compose the Select expression from scratch in order to inline the expression that's your dynamic filter. This might be extra hard with anonymous types, i'm not sure. I just found the following article, it seems to explain this pretty well: http://www.codeproject.com/KB/linq/rewrite_linq_expressions2.aspx

呆° 2024-10-09 02:32:48

我从 MSDN 上摘下来的东西:这个想法是你只需将它指向一个现有的函数:

using System;

public class 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))

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

Something I grabbed off of MSDN: the idea is that you just point it to an existing function:

using System;

public class GenericFunc

{
   public static void Main()
   {
      Func<string, string> convertMethod = UppercaseString;
   }

   private static string UppercaseString(string inputString)
   {
      return inputString.ToUpper();
   }
}

I'm sure there are also other ways. I remember doing something like

new Func<WorkItem, bool>((item => item.projectId == criteria.ProjectId))

But I'm not sure. anymore, I'm quite sure you need the "new" though, hope this helps :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文