将IEnumerable转换为IQueryable是否枚举查询

时间:2015-03-24 11:09:18

标签: c# jquery linq predicate

我正在使用JQuery小部件的数据表在MVC应用程序中使用服务器端分页,排序和过滤的表控件。在进行过滤时,我有以下方法:

private IQueryable<ImportRfqViewModel> BuildLinqQuery(System.Collections.Specialized.NameValueCollection query)
{
    var result = query.GetValues("filterslength");
    var filtersCount = int.Parse(query.GetValues("filterslength")[0]);
    if (result == null || filtersCount == 0)
    {
        return AllImportRfq();
    }

    Predicate<ImportRfqViewModel> orResultPredicate = PredicateExtensions.False<ImportRfqViewModel>();
    for (var i = 0; i < filtersCount; i += 1)
    {
        var filterValue = query.GetValues("filtervalue" + i)[0].ToUpper();
        var filterCondition = query.GetValues("filtercondition" + i)[0];
        var filterDataField = query.GetValues("filterdatafield" + i)[0];
        var filterOperator = query.GetValues("filteroperator" + i)[0];

        if (filterDataField == "ImportRfqId")
        {
            Predicate<ImportRfqViewModel> predicate = p => p.ImportRfqId.ToString().Contains(filterValue);
            orResultPredicate = orResultPredicate.Or(predicate);
        }
        else if (filterDataField == "DateCreated")
        {
            Predicate<ImportRfqViewModel> predicate = p => p.DateCreated.ToString("yyyy/MM/dd hh:mm:ss").Contains(filterValue);
            orResultPredicate = orResultPredicate.Or(predicate);
        }
        ...
    }

    Func<ImportRfqViewModel, bool> funcOr = l => orResultPredicate(l);

    var allResearch = AllImportRfq().Where(funcOr).AsQueryable();
    return allResearch;
}

我正在使用谓词来链接或条件。我显然想要返回一个IQueryable,以便在我到达该部分之前不运行查询:

dbResult = dbResult.Skip(pagesize * pagenum).Take(pagesize);

谓词的结果是IEnumerable。这就是我调用.AsQueryable();

的原因

我关心并且不知道的是,如果我有意义的话,该事物是否可能枚举查询然后返回IQueryable然后丢弃枚举。

在所有这些中,我假设如果我返回IEnumerable,它将执行查询。

1 个答案:

答案 0 :(得分:2)

单独返回IEnumerable并不意味着您实际上正在执行查询。这取决于IEnumerable的创建者,但通常IEnumerable被视为 lazy ,只有在枚举IEnumerator时才触及基础数据源。 Linq运算符和扩展方法表现良好,因此AsQueryable()调用不会枚举目标,您应该是安全的。

是的,您是否尝试过更改代码:

Func<ImportRfqViewModel, bool> funcOr = l => orResultPredicate(l);

到此(只要您的查询提供程序完全支持Where和您正在构建的谓词)?

Expression<Func<ImportRfqViewModel, bool>> funcOr = ...;

通过这种方式,您应该能够避免在IQueryableIEnumerable之间来回走动,您根本不需要调用AsQueryable(),因此您不会再怀疑。如果您的查询提供程序支持它,它将比您正在执行的操作更有效,这将在查询基础数据源后执行过滤。

编辑:为了让它更清晰,从Func<>迁移到Expression<>不仅仅是改变变量的类型,它实际上意味着你' d必须检查构建谓词的整个过程,以便始终通过编写Expression实例而不只是Func个实例来工作,否则您的结果表达式树将很难被您的查询提供程序理解。< / p>