使用Linq进行多级where子句过滤

4

假设我有一些筛选条件,通过一组CustomerFilter对象传递给我的应用程序,我需要运行一个Linq to Entities查询,并根据这些过滤器返回结果。

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

筛选对象:

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

示例数据:

CustomerID    LocationID 

1             1

              2

              3

              4 

2             2 

              3 


              4

我可以很容易地按照外部CustomerID构建查询过滤器,如下所示。 < p > < em > 查询:

    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子句会导致错误的结果,因为它会拉取具有匹配LocationIDs的其他CustomerIDs。

有什么想法可以在传入的CustomerFilter对象中实现这个多级过滤吗?

2个回答

6

稍作修改。基本上,我们使用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);

由于Lambda表达式中的LocationID存在作用域问题,它无法编译。一个名为“w”的局部变量无法在此作用域中声明,因为它会赋予“w”不同的含义,而“w”已经在“父级或当前”作用域中用于表示某些内容。 - Phil Murray
2
@mattytommo,我调整了你的代码,因为你试图在两个不同的作用域中使用名为w的变量:你在Where lambda和a.LocationID.Any中都有它,所以它会生成@PhilMurray的编译器错误。我相信这应该可以解决问题。 - Corey Adler
1
嘿,你就是回答 OP 问题的高手。你获得好处是理所应当的。 - Corey Adler

0

为了快速查找(在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是过滤器的数量,mPortal_SurveyLocations中项目的数量。


2
这能直接映射到Linq to Entities吗? - Mathew Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接