将 IEnumerable 转换为 IQueryable 是否枚举查询
Does converting an IEnumerable to IQueryable enumerate the query
我正在使用 JQuery 小部件的数据table 在具有服务器端分页、排序和过滤功能的 MVC 应用程序中有一个 table 控件。在进行过滤时,我有以下方法:
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;
}
我正在使用谓词来链接 Or 条件。我显然想要 return 一个 IQueryable 以便在我到达部分之前查询不是 运行:
dbResult = dbResult.Skip(pagesize * pagenum).Take(pagesize);
虽然谓词的结果是 IEnumerable
。这就是为什么我称 .AsQueryable();
我担心但不知道的是,如果我是有道理。
在所有这一切中,我假设如果我 return 一个 IEnumerable
,它将执行查询。
返回 IEnumerable
本身并不意味着您实际上正在执行查询。这取决于 IEnumerable
的创建者,但通常 IEnumerable
被认为是 惰性 ,并且仅在枚举 IEnumerator
时才触及基础数据源。 Linq 运算符和扩展方法表现良好,因此您的 AsQueryable()
调用不会枚举目标,您应该是安全的。
顺便说一句,您是否尝试过更改您的代码:
Func<ImportRfqViewModel, bool> funcOr = l => orResultPredicate(l);
对此(当然,只要您的查询提供程序完全支持 Where
和您正在构建的谓词)?
Expression<Func<ImportRfqViewModel, bool>> funcOr = ...;
这样你应该能够避免在 IQueryable
和 IEnumerable
之间来回切换,你根本不需要调用 AsQueryable()
,因此你没有更多疑惑。如果你的查询提供者支持它,它会比你现在做的更有效率,它会在查询底层数据源后执行过滤。
编辑:为了更清楚,从 Func<>
到 Expression<>
的移动不仅仅是改变变量类型的问题,这实际上意味着您必须回顾构建谓词的整个过程,以便您始终通过组合 Expression
个实例来工作,而不仅仅是 Func
个实例,否则您的结果表达式树将很难理解您的查询提供者。
我正在使用 JQuery 小部件的数据table 在具有服务器端分页、排序和过滤功能的 MVC 应用程序中有一个 table 控件。在进行过滤时,我有以下方法:
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;
}
我正在使用谓词来链接 Or 条件。我显然想要 return 一个 IQueryable 以便在我到达部分之前查询不是 运行:
dbResult = dbResult.Skip(pagesize * pagenum).Take(pagesize);
虽然谓词的结果是 IEnumerable
。这就是为什么我称 .AsQueryable();
我担心但不知道的是,如果我是有道理。
在所有这一切中,我假设如果我 return 一个 IEnumerable
,它将执行查询。
返回 IEnumerable
本身并不意味着您实际上正在执行查询。这取决于 IEnumerable
的创建者,但通常 IEnumerable
被认为是 惰性 ,并且仅在枚举 IEnumerator
时才触及基础数据源。 Linq 运算符和扩展方法表现良好,因此您的 AsQueryable()
调用不会枚举目标,您应该是安全的。
顺便说一句,您是否尝试过更改您的代码:
Func<ImportRfqViewModel, bool> funcOr = l => orResultPredicate(l);
对此(当然,只要您的查询提供程序完全支持 Where
和您正在构建的谓词)?
Expression<Func<ImportRfqViewModel, bool>> funcOr = ...;
这样你应该能够避免在 IQueryable
和 IEnumerable
之间来回切换,你根本不需要调用 AsQueryable()
,因此你没有更多疑惑。如果你的查询提供者支持它,它会比你现在做的更有效率,它会在查询底层数据源后执行过滤。
编辑:为了更清楚,从 Func<>
到 Expression<>
的移动不仅仅是改变变量类型的问题,这实际上意味着您必须回顾构建谓词的整个过程,以便您始终通过组合 Expression
个实例来工作,而不仅仅是 Func
个实例,否则您的结果表达式树将很难理解您的查询提供者。