Lambda and Nested Objects
我看了一下这个答案,部分地解决了我的问题。
不过,我需要的是以下内容。
因为我有一个目标;
1 2 3 | Product string code List<suitability> items |
然后我有了这个物体;
1 2 3 | Suitability key value |
每个产品都有不同数量的[项目],不同产品的键/值对也不同。
在搜索时,我会得到一个合适对象的列表。我现在需要搜索包含(全部)所提供的适用性对象的所有产品。
因此,例如,产品可能具有"牙科=真"和"治疗=真"。
我可能会收到一个要求,所有产品的牙科=真和治疗=假。
首先,我要指出的是,键值对(又称EAV模型)对于表示这种数据来说是一个糟糕的选择,这个问题是一个很好的例子,说明为什么要搜索任意属性集合比搜索特定属性困难得多。
当然,这仍然可以做到:
1 2 3 4 5 6 | 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; |
与嵌套属性相比,在实际具有
如果需要查询的项目数可能会发生变化,那么处理这一问题的最简单方法是将过滤器链接在一起:
1 2 3 4 5 6 7 8 9 | 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 |
如果您正在寻找一种更"实用"的方法来实现它而不需要链接,那么:
1 2 3 4 5 | 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); |
使用谓词生成器(来自LinqPad的作者),可以从编译时未知的一组条件构建查询。以下内容应足够:
1 2 3 4 5 6 7 8 9 10 11 | 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作为源代码,结果集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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()); |