经过几个小时的尝试和搜索,我认为是时候与你分享我的问题了。
问题定义: 我有一个 KeyValuePairs字典(名为 filterPool ),其中包含一个整数( PropertyID )和一个字符串( McValue )。我想要做的是根据KeyValuePairs过滤产品并将它们作为 DataTable / List 返回。 您可以将此视为构建动态“Where ... And ..”子句为SQL。
以下是我正在使用的代码:
foreach (KeyValuePair<int, string> filter in filterPool)
{
products = products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value));
}
return products.ToDataTable();
问题是上面的foreach循环似乎只运行一次,对于Dictionary中可用的最新KeyValuePair。
据我所知,在Stackoverflow上,我问题的最接近的解决方案是:this one, also using a Dictionary of values for filtering
必须有办法实现使用Dictionary和LINQ过滤的目标;或者有一件很重要的事情,我不知道/忽视了什么。
希望所给出的问题足够清楚, 谢谢 ^^
答案 0 :(得分:2)
这是一个关闭问题。你可以通过临时解决它:
foreach (KeyValuePair<int, string> filterTmp in filterPool)
{
var filter = filterTmp; // Make a temporary
products = products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value));
}
return products.ToDataTable();
有关正在发生的事情的详细信息,请参阅Eric Lippert的帖子Closing over the loop variable considered harmful。
另请注意,C#5的此行为已更改。在C#5 / VS2012中,此代码将按预期工作。
答案 1 :(得分:1)
您在foreach的每次迭代中都会覆盖您的产品系列。我不确定你的收藏中的数据类型是什么,但你要在foreach中做这样的事情:
products.AddRange(products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value)));
我不确定这是否合理,但您似乎正在尝试创建一个包含与您的filterPool相匹配的产品的集合。
答案 2 :(得分:0)
我认为使用聚合更好地解决了这个问题:
return filter
.Aggregate(products, (acc, filter) => acc.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value)));
.ToDataTable();