代码之家  ›  专栏  ›  技术社区  ›  griegs

lambda和嵌套对象

  •  1
  • griegs  · 技术社区  · 14 年前

    我看了一眼 this 回答,这部分是为了解决我的问题。

    不过,我需要的是以下内容。

    因为我有一个目标;

    Product
      string code
      List<suitability> items
    

    然后我有了这个物体;

    Suitability
      key
      value
    

    每个产品都有不同数量的[项目],不同产品的键/值对也不同。

    在搜索时,我会得到一个合适对象的列表。我现在需要搜索所有包含(全部)所提供的适用性对象的产品。

    因此,例如,产品可能具有“牙科=真”和“治疗=真”。

    我可能会收到一个要求,所有产品的牙科=真和治疗=假。

    2 回复  |  直到 14 年前
        1
  •  1
  •   Simon Fox    14 年前

    使用 PredicateBuilder (来自linqpad的作者)您可以从编译时未知的一组条件构建查询。以下内容应足够:

    var predicate = PredicateBuilder.True<Product>();
    
    foreach (Suitability criteria in searchCriteria)
    {
        string tempKey = criteria.Key;
        string tempValue = criteria.Value;
        predicate = predicate.And(p => 
                         p.Items.Any(s => s.Key == tempKey && s.Value == tempValue));
    }
    
    return dataContext.Products.Where(predicate.Compile());
    

    更新:这里有一些我测试过的示例代码,它使用IEnumerable作为源代码,结果集 productsResult 包含中的第一个和第二个产品 products 名单:

    var searchCriteria = new List<Suitability>()
        {
            new Suitability() { Key="a", Value="b" },
            new Suitability() { Key="a", Value="c" }
        };
    
    var products = new List<Product>()
        {
            new Product()
                {
                    Items = new List<Suitability>() {
                                new Suitability() { Key="a", Value="b" },
                                new Suitability() { Key="a", Value="c" }}
                },
            new Product()
                {
                    Items = new List<Suitability>() {
                                new Suitability() { Key="a", Value="b" },
                                new Suitability() { Key="a", Value="c" },
                                new Suitability() { Key="b", Value="c" }}
                },
            new Product()
                {
                    Items = new List<Suitability>() {
                                new Suitability() { Key="c", Value="d" }}
                }
        };
    
        var predicate = PredicateBuilder.True<Product>();
    
        foreach (Suitability criteria in searchCriteria)
        {
            string tempKey = criteria.Key;
            string tempValue = criteria.Value;
            predicate = predicate.And(p => p.Items.Any(
                             s => s.Key == tempKey && s.Value == tempValue));
        }
    
        IEnumerable<Product> productsResult = products.Where(predicate.Compile());
    
        2
  •  2
  •   Aaronaught    14 年前

    首先,我要指出的是,键值对(又称EAV模型)对于表示这种数据来说是一个糟糕的选择,这个问题是一个很好的例子,说明为什么要搜索任意属性集合比搜索特定属性困难得多。

    当然,这仍然可以做到:

    var suitableProducts =
        from p in products
        where
            p.Items.Any(s => s.Key == "dental" && s.Value == "true") &&
            p.Items.Any(s => s.Key == "therapies" && s.Value == "false")
        select p;
    

    它不像在 Product 实际拥有的类 dental therapies 属性,而不是嵌套属性。

    如果你需要的物品数量 查询 可以更改,那么最简单的处理方法是将过滤器链接在一起:

    var searchItems = ...
    var result = products;
    foreach (var searchItem in searchItems)
    {
        result = result.Where(p =>
            p.Items.Any(s => s.Key == searchItem.Key &&
                             s.Value == searchItem.Value));
    }
    // Do something with result
    

    如果您正在寻找一种更“实用”的方法来实现它而不需要链接,那么:

    var suitabilityConditions = searchItems.Select(i =>
        (Predicate<Product>)(p => p.Items.Any(s => 
            s.Key == searchItem.Key && s.Value == searchItem.Value)));
    Predicate<Product> match = p => suitabilityConditions.All(c => c(p));
    var suitableProducts = products.Where(match);