【发布时间】:2017-01-12 19:16:35
【问题描述】:
我需要将这两种方法合并为一个泛化它们。我知道 IQueryable 实现了 IEnumerable,IOrderedQueryable 实现了 IOrderedEnumerable,如果存在第二种方法,第一种方法似乎没用。但是由于某些实体框架的原因,第二个破坏了服务器端查询转换(Linq-to-SQL)
private static IQueryable<T> Pag<T>(IOrderedQueryable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
private static IEnumerable<T> Pag<T>(IOrderedEnumerable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
这些方法违反了DRY 规则,非常烦人。
【问题讨论】:
-
您的代码混淆成功。学习使用自我描述的变量名称。话虽如此,请展示您如何调用此代码。
-
您需要展示一个完整、可缩小且可验证的示例,以显示 EF 无法在 Linq 中转换为 SQL。
-
此代码只是对数据库查询的结果进行分页。如果 linq 在 IQueryable 集合上工作,则 linq-to-sql 会从数据库中检索所需的行。注释 IQueryable 方法后,代码仍然可以使用 IEnumerable 方法工作,但查询会从数据库处理本身检索所有数据,而不是将作业留给数据库,从而对性能产生不利影响。
-
为什么需要指定totalRows? Take(diff > reqLength ? reqLength : diff) Take 中的条件计数不是必需的(对于 IEnumerable 来说绝对是),我相信大多数其他 DataProviders 都是这种情况。它可能只是 Take(totalRows).Skip(...).Take(reqLength) 因为如果您指定的值大于可用的值,则该参数是允许的。
-
我之前在代码中使用过 Count()。最好不要在必要时调用它。
标签: c# linq linq-to-sql generalization