C# 使用Linq进行多级where子句筛选

C# 使用Linq进行多级where子句筛选,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,假设我通过CustomerFilter对象数组将一些筛选条件传递到我的应用程序中,我需要在其中运行一个查询,并基于这些筛选从Linq到Entities查询返回结果 因此,在这种情况下,客户将通过服务调用向我传递CustomerFilter对象数组 筛选对象: 示例数据: 我可以很容易地在外部CustomerID上构建一个查询过滤,如下所示 查询: public void GetCustomerResults(列出帐户) { 列出客户=(从帐户中选择a.CustomerID).ToList();

假设我通过CustomerFilter对象数组将一些筛选条件传递到我的应用程序中,我需要在其中运行一个查询,并基于这些筛选从Linq到Entities查询返回结果

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

筛选对象:

示例数据:

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

查询:

public void GetCustomerResults(列出帐户)
{
列出客户=(从帐户中选择a.CustomerID).ToList();
变量位置=ctx.Portal\u测量位置
.Where(w=>customer.Contains(w.CustNum))
.OrderBy(o=>o.LocationKey);
}
因此,我可以根据外部条件进行筛选,但我不确定如何根据每个CustomerID的多个位置ID进行筛选。显然,仅仅放置OR子句将给出不正确的结果,因为它将使用匹配的LocationID拉入其他CustomerID


考虑到传入的CustomerFilter对象,您对如何完成此多级筛选有何想法?

轻微返工。基本上,我们使用
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);
为了快速查找(在
列表上使用
包含
不是很快),可以从过滤器对象创建哈希集字典

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

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);
}
public void GetCustomerResults(列出帐户){
查字典=
accounts.ToDictionary(a=>a.CustomerID,a=>newhashset(a.LocationID));
变量位置=
ctx.Portal_测量位置
.其中(w=>
lookup.ContainsKey(w.CustNum)&&
查找[w.CustNum]。包含(w.LocationKey))
.OrderBy(o=>o.LocationKey);
}

字典和哈希集都具有查找项的
O(1)
复杂度,因此整个操作获得
O(n+m)
复杂度,其中
n
是过滤器的数量,而
m
Portal\u SurveyLocations

中的项目数,这会直接映射到Linq to Entities吗?我认为,它不会编译,因为,LocationID上的lamba表达式存在作用域问题。任何名为“w”的局部变量都不能在此作用域中声明,因为它将赋予“w”不同的含义,已在“父级或当前”范围中用于表示something@mattytommo我调整了您的代码,因为您试图在两个不同的范围内使用名为
w
的变量:对于
Where
lambda以及
a.LocationID.Any
1,它会生成@PhilMurray的编译器错误。我相信这应该可以解决问题。嘿,是你找到了OP问题的答案。你从中受益才是公平的。
    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);
    }
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);
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);
}