【问题标题】:Multiple level where clause filtering with Linq使用 Linq 进行多级 where 子句过滤
【发布时间】:2014-12-18 12:45:48
【问题描述】:

假设我有一些过滤条件通过 CustomerFilter 对象数组传递到我的应用程序,我需要在其中运行查询并根据来自 Linq 到实体查询的这些过滤器返回结果。

因此,在这种情况下,客户将通过服务调用将 CustomerFilter 对象数组传递给我。

过滤对象:

class CustomerFilter
{
    public string CustomerID;
    public int[] LocationID;
}

示例数据:

CustomerID    LocationID 

1             1

              2

              3

              4 

2             2 

              3 


              4

我可以很容易地在外部 CustomerID 上构建查询过滤,如下所示。

查询:

    public void GetCustomerResults(List<CustomerFilter> accounts)
    {
        List<string> customer = (from a in accounts select a.CustomerID).ToList();

        var locations = ctx.Portal_SurveyLocations
                            .Where(w => customer.Contains(w.CustNum))
                            .OrderBy(o => o.LocationKey);
    }

所以我可以按外部条件进行过滤,但我不确定如何按每个 CustomerID 的多个位置 ID 进行过滤。显然,仅仅放置一个 OR 子句会产生不正确的结果,因为它会拉入具有匹配 LocationID 的其他 CustomerID。

在给定传入的 CustomerFilter 对象的情况下,关于如何完成这个多级过滤器的任何想法?

【问题讨论】:

    标签: c# linq linq-to-entities


    【解决方案1】:

    轻微返工。基本上,我们使用Any的组合来遍历子集合,达到想要的结果。

    var locations = ctx.Portal_SurveyLocations
        .Where(w => accounts.Any(a => a.CustomerID == w.CustNum &&
                                      a.LocationID.Any(l => w.LocationKey == l)))
        .OrderBy(o => o.LocationKey);
    

    【讨论】:

    • 它无法编译,因为我认为 LocationID 上的 Lamba 表达式存在范围问题。Any w 不能在此范围内声明名为“w”的局部变量,因为它会给出与“w”不同的含义,它已在“父级或当前”范围内用于表示某事
    • @mattytommo 我调整了您的代码,因为您试图在 2 个不同的范围内使用名为 w 的变量:您将它用于 Where lambda 和 a.LocationID.Any 一个,并且所以它产生了@PhilMurray 的编译器错误。我相信这应该可以解决问题。
    • 嘿,你是回答 OP 问题的人。从中受益才是公平的。
    【解决方案2】:

    为了快速查找(在 List 上使用 Contains 不是很快),您可以从过滤器对象创建哈希集字典。

    字典将包含每个客户的一个项目,该项目中的值将是位置的哈希集。使用时,首先检查客户是否在字典中,然后检查位置是否在该客户的哈希集中:

    public void GetCustomerResults(List<CustomerFilter> accounts) {
      Dictionary<string, HashSet<int>> lookup =
        accounts.ToDictionary(a => a.CustomerID, a => new HashSet<int>(a.LocationID));
    
        var locations =
          ctx.Portal_SurveyLocations
          .Where(w =>
            lookup.ContainsKey(w.CustNum) &&
            lookup[w.CustNum].Contains(w.LocationKey))
          .OrderBy(o => o.LocationKey);
    }
    

    字典和散列集都具有O(1) 查找项目的复杂度,因此整个操作得到O(n+m) 复杂度,其中n 是过滤器的数量,m 是数量Portal_SurveyLocations 中的项目数。

    【讨论】:

    • 这个映射会直接映射到 Linq to Entities 中吗?
    猜你喜欢
    • 2015-04-10
    • 1970-01-01
    • 2018-03-10
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多