我有一个采用IOrderedQueryable和Expression <Func <T,V >>的方法,该方法用作过滤器和来自SQL数据库的页面记录。
var query = contexBills.AsNoTracking().Where(x => x.Complete==true).OrderBy(x => x.BillID);
var reader = new BulkReader<Bill>(query, x => x.BillId, 10000);
批量阅读器在整个代码中得到广泛使用,以分页处理大量记录并分批处理它们,其定义如下
public BulkReader(IOrderedQueryable<T> queryable, Expression<Func<T, Object>> selector, int blockSize = 1000)
为了优化,分页从表中找到的最小值开始,到最大值为止。由于使用Skip()。Take()方法每月在数据库中有数百万条记录,当您到达表中的数百万条记录并处理整个月的数据时,它会降级到每页约13秒小时。
假设集合中只有极少数记录被标记为complete == false,则只需选择记录> = [Page Start] AND <[Page End]即可非常迅速地工作,每分钟大约一百万条记录。在某些情况下,您处理的数据量略小于传入的blockSize,但要处理介于min和max之间的所有记录。
随着月份的增加,最小值增加,因此,假设最小值为0会浪费大量SQL调用,而这些调用根本不会返回任何内容。
所以我要获得这些值是
var min = queryable.Select(selector).DefaultIfEmpty(0).Min();
var max = queryable.Select(selector).DefaultIfEmpty(0).Max();
产生如下所示的SQL
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
MIN([Join1].[A1]) AS [A1]
FROM ( SELECT
CASE WHEN ([Project1].[C1] IS NULL) THEN 0 ELSE [Project1].[PrintSummaryID] END AS [A1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent1].[PrintSummaryID] AS [PrintSummaryID],
cast(1 as tinyint) AS [C1]
FROM [dbo].[tblPrintSummary] AS [Extent1] ) AS [Project1] ON 1 = 1
) AS [Join1]
) AS [GroupBy1]
GO
如果我手动编写代码(作为测试)来进行这样的调用
var min = queryable.Min(x =>(int?)x.BillID) ?? 0;
var max = queryable.Max(x =>(int?)x.BillID) ?? 0;
那么产生的SQL是
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
MIN([Extent1].[PrintSummaryID]) AS [A1]
FROM [dbo].[tblPrintSummary] AS [Extent1]
) AS [GroupBy1]
GO
通过声明以下内容,可以实现相同的目的:
Expression<Func<Bill, int?>> selector2 = x => x.BillID;
这带来了更简单,更快的SQL执行的好处,并使代码成为:
var min = queryable.Select(selector2).Min() ?? 0;
var max = queryable.Select(selector2).Max() ?? 0;
采用显式重新定义所有选择器并为其提供覆盖的方法将意味着在整个应用程序中进行大量重复和重新编码
我如何才能采用原始选择器,然后一般地转换为可为空的版本,而不是必须显式地编码每个选择器。
var selector2 = selector.NullableExpression();
我想以此作为对Expression <Func <T,V >>的扩展方法NullableExpression(),以便我返回ExpressionExpression <Func <T,Nullable <V >>>,这样我就可以在其他方法中使用它我的代码中的所有位置。
我正在努力将V转换为Nullable或V?在表达中。
真的很简单。诀窍是在重新使用其源表达式的同时使用源表达式的主体。
public static Expression<Func<T, V?>> ToNullableExpression<T, V>
(this Expression<Func<T, V>> source) where V : struct
{
if(source == null)
throw new ArgumentNullException("source");
var body = Expression.Convert(source.Body, typeof(V?));
var parameters = source.Parameters;
return Expression.Lambda<Func<T, V?>>(body, parameters);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句