我看了一下this的答案,这部分是为了解决我的问题。
但是,我需要的是以下内容。
鉴于我有一个对象;
Product
string code
List<suitability> items
然后我有了这个对象;
Suitability
key
value
每个产品都有可变数量的[项目],键/值对因产品而异。
搜索时,我会得到一个Suitability对象列表。我现在需要搜索包含(所有)提供的适用性对象的所有产品。
例如,产品可能有牙齿=真,疗法=真。
我可能会收到所有牙齿= true且疗法=假的产品的请求。
答案 0 :(得分:2)
首先,我想指出,键值对(AKA 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);
答案 1 :(得分:1)
使用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());