动态表查询

时间:2017-12-18 16:52:56

标签: c# linq

我有以下Tuples列表,我填写了标题/列名称,后面跟着可以在该列中找到的值列表。然后我想用整个列表查询DataTable

List<Tuple<string, IEnumerable<string>>> filters = new List<Tuple<string, IEnumerable<string>>>();

现在我正在执行以下操作,将每个作为单独的查询运行,在循环中逐个过滤。但我相信应该有一种方法可以做到这一点,而无需循环和运行多个查询。即立即将所有查询一起应用。

var dataTemp = MyDataTable.AsEnumerable();
foreach (var filter in filters)
{
datTemp = datTemp.Where(row => filter.Item2.Contains(row.Field<String>(filter.Item1)));
}
return dataTemp;

2 个答案:

答案 0 :(得分:1)

您应该能够针对所有过滤器测试每一行:

var dataTemp = MyDataTable.AsEnumerable()
                   .Where(row => filters.All(filter => filter.Item2.Contains(row.Field<string>(filter.Item1))));

根据过滤器IEnumerable<string>的性质,您可能希望转换过滤器以加快处理速度:

var fastFilters = filters.Select(f => (f.Item1, new HashSet<string>(f.Item2)));

var dataTemp = MyDataTable.AsEnumerable()
                   .Where(row => fastFilters.All(filter => filter.Item2.Contains(row.Field<string>(filter.Item1))));

我通常使用扩展程序将IEnumerable<>转换为HashSet

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) => new HashSet<T>(source);

然后你可以

var fastFilters = filters.Select(f => (f.Item1, f.Item2.ToHashSet()));

答案 1 :(得分:0)

这是linq查询:

filters.Aggregate(dataTemp, 
            (current, filter) => current.Where(row => filter.Item2.Contains(row.Field<string>(filter.Item1))));

您还可以实现扩展方法:

    public static EnumerableRowCollection<DataRow> CustomFilter(this DataTable @this,
        IEnumerable<Tuple<string, IEnumerable<string>>> filters)
    {
        var dataTemp = @this.AsEnumerable();
        return filters.Aggregate(dataTemp, 
            (current, filter) => current.Where(row => filter.Item2.Contains(row.Field<string>(filter.Item1))));
    }