J'ai une méthode qui prend un IOrderedQueryable et d'expression < Func < T, V >> qui utilise comme un filtre et la page des enregistrements d'une base de données SQL.Convert expression <Func<T, V>> à l'expression <Func <T, Nullable <V> >>
var query = contexBills.AsNoTracking().Where(x => x.Complete==true).OrderBy(x => x.BillID);
var reader = new BulkReader<Bill>(query, x => x.BillId, 10000);
le lecteur en vrac est largement utilisé à travers le code à la page d'importants volumes de dossiers et de les traiter par lots et est défini comme celui-ci
public BulkReader(IOrderedQueryable<T> queryable, Expression<Func<T, Object>> selector, int blockSize = 1000)
Pour la radiomessagerie d'optimisation commence à la valeur minimale trouvée dans la table et se termine à la valeur maximale. Comme il y a plusieurs millions d'enregistrements par mois dans la base de données en utilisant une approche Skip(). Take() se réduit à environ 13 secondes par page lorsque vous atteignez les millions dans la table et que le traitement des mois entiers peut prendre plusieurs heures. Etant donné qu'il y a très peu d'enregistrements dans l'ensemble qui sont marqués comme complets == false, il suffit de sélectionner les enregistrements> = [Page Start] ET < [Page End] fonctionne très rapidement à environ un million d'enregistrements par minute. Dans certains cas, vous traitez légèrement moins que blockSize transmis mais tous les enregistrements entre min et max sont traités. Au fur et à mesure que les mois avancent, la valeur minimale augmente, en supposant que 0 en tant que minimum gaspille beaucoup d'appels SQL qui ne renvoient rien du tout.
Alors ce que je dois obtenir ces valeurs est
var min = queryable.Select(selector).DefaultIfEmpty(0).Min();
var max = queryable.Select(selector).DefaultIfEmpty(0).Max();
qui produit SQL qui ressemble à ceci
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
Si je tends le code (comme un test) pour faire des appels comme celui-ci
var min = queryable.Min(x =>(int?)x.BillID) ?? 0;
var max = queryable.Max(x =>(int?)x.BillID) ?? 0;
puis le SQL produit est
SELECT
[GroupBy1].[A1] AS [C1]
FROM (SELECT
MIN([Extent1].[PrintSummaryID]) AS [A1]
FROM [dbo].[tblPrintSummary] AS [Extent1]
) AS [GroupBy1]
GO
La même chose peut être atteint en déclarant ce qui suit à la place:
Expression<Func<Bill, int?>> selector2 = x => x.BillID;
Ce qui donne l'avantage de l'exécution SQL plus simple et plus rapide et permet le code de devenir:
var min = queryable.Select(selector2).Min() ?? 0;
var max = queryable.Select(selector2).Max() ?? 0;
Prendre la Une approche consistant à redéfinir explicitement tous les sélecteurs et à leur fournir des substitutions signifierait une duplication et un recodage significatifs dans l'ensemble de l'application
Comment puis-je prendre un sélecteur d'origine et faire une conversion à l'équivalent de la version Nullable génériquement plutôt que d'avoir à coder explicitement chacun d'eux.
var selector2 = selector.NullableExpression();
je voudrais pour cela comme une méthode d'extension NullableExpression() sur l'expression < Func < T, V >> afin que je retourne un ExpressionExpression < Func < T, Nullable < V >>> et que comme je pourrais l'utiliser dans d'autres endroits tout au long de mon code.
Je suis aux prises avec la façon dont je peux convertir le V en Nullable ou en V? dans une expression.
travaillé comme un charme ... Merci beaucoup ... –
j'utiliser ExpressionVisitor moi-même, car dans certains cas, vous pourriez avoir des problèmes avec EntityFramework, si l'expression source est pas tout à fait transitoire. C'est à dire que si le résultat et l'entrée sont liés à EntityFramework, une exception sera throw. – Aron
Vous pouvez également utiliser Intercepteur de requête de David Fowl pour convertir dynamiquement '.Min (prédicat) ?? 0' à '.Min (predicate.ToNullableExpression())' à Execute(). – Aron