1

我有可变数量的“过滤器”应用于实体集合,这些过滤器存储在列表中。现在,我正在执行以下操作:

    IQueryable<Items> items = SharedContext.Context.Items.GetAll();
    //This list is dynamic, but shown static here for simplicity
    IEnumerable<Items> filterList = new List<string>(){"new", "old", "current"};
    IEnumerable<Item> items_temp = new List<Item>();
    foreach (string type in filterList)
    {
        var temp = items.Where(i => i.Type.ToLower().Trim() == type.ToLower().Trim());
        items_temp = items_temp.Union(temp);
    }
    items = items_temp.AsQueryable();

不幸的是,这会导致巨大的性能问题。我知道有人有更好的解决方案......你们怎么看?

编辑
使用上面的代码运行我的应用程序大约需要 30 秒才能执行,但如果执行以下操作:

    items.Where(item => item.Type.ToLower().Trim() == "new" ||
                        item.Type.ToLower().Trim() == "old" ||
                        item.Type.ToLower().Trim() == "current");

我的应用程序在大约 4 秒内执行。谁能想到一个可以匹配这种性能的解决方案,或者至少让我了解为什么结果如此不同?仅供参考,我将我的数据绑定到一个网格,其中嵌套了多个网格......一个小的改进可能会有很长的路要走。

4

2 回答 2

4

听起来你想要的是这样的:

var items = SharedContext.Context.Items.GetAll();
IEnumerable<string> filterList = new List<string>(){"new", "old", "current"};
var filteredItems = items.Where(i => filterList.Contains(i.Type.ToLower()));

如果您对此有疑问,您可能想尝试使用数组:

string[] filterList = new string[] {"new", "old", "current"};
var filteredItems = items.Where(i => filterList.Contains(i.Type.ToLower()));

更新:这是另一个动态生成过滤器表达式的策略:

var filterList = new[] { "new", "old", "current" };
var param = Expression.Parameter(typeof(Item));
var left = 
    Expression.Call(
        Expression.Call(
            Expression.PropertyOrField(param, "Type"),
            typeof(string).GetMethod("ToLower", Type.EmptyTypes)),
        typeof(string).GetMethod("Trim", Type.EmptyTypes));
var filterExpr = (Expression<Func<Item, bool>>)Expression.Lambda(
    filterList
        .Select(f => Expression.Equal(left, Expression.Constant(f)))
        .Aggregate((l, r) => Expression.OrElse(l, r)), 
    param);
var filteredItems = items.Where(filterExpr);
于 2013-07-25T17:21:14.840 回答
2

您可以进行连接以过滤项目:

IEnumerable<Items> filterList = new List<string>(){"new", "old", "current"};          
IQueryable<Items> items = SharedContext.Context.Items.GetAll();

var filteredItems = from i items
                    join f in filterList 
                      on i.Type.ToLower().Trim() equals t.ToLower().Trim()
                    select i;
于 2013-07-25T17:35:49.607 回答