gpt4 book ai didi

c# - 将 Expression> 转换为 Expression>>

转载 作者:太空狗 更新时间:2023-10-30 01:05:33 26 4
gpt4 key购买 nike

我有一个采用 IOrderedQueryable 和 Expression > 的方法,后者用作 SQL 数据库中的过滤器和页面记录。

var query = contexBills.AsNoTracking().Where(x => x.Complete==true).OrderBy(x => x.BillID);

var reader = new BulkReader<Bill>(query, x => x.BillId, 10000);

bulk reader在整个代码中被广泛使用,对大量记录进行分页并分批处理,定义如下

public BulkReader(IOrderedQueryable<T> queryable, Expression<Func<T, Object>> selector, int blockSize = 1000)

对于优化分页,从表中找到的最小值开始,到最大值结束。由于数据库中每月有数百万条记录,使用 Skip().Take() 方法会降低到每页约 13 秒,当您达到表中的数百万条记录时,处理整个月的数据可能需要很多时间小时。

鉴于集合中标记为 complete == false 的记录非常少,因此只需选择记录 >= [Page Start] AND < [Page End] 就可以非常快速地以每分钟大约一百万条记录的速度工作。在某些情况下,您处理的数据略小于传入的 blockSize,但会处理最小值和最大值之间的所有记录。

随着月份的推移,最小值会增加,因此假设 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 > 上的 NullableExpression() 扩展方法,以便我返回 ExpressionExpression >> 这样我就可以使用它在我的代码中的其他位置。

我正在为如何将 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);
}

关于c# - 将 Expression<Func<T, V>> 转换为 Expression<Func<T, Nullable<V>>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18395581/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com