Skip to content

Optimize GetQueryableMethod() #394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions Orm/Xtensive.Orm/Linq/QueryableVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,16 @@ mc.Arguments is var mcArguments
/// <param name="call">A call to process.</param>
/// <returns><see cref="QueryableMethodKind"/> for the specified expression,
/// or null if method is not a LINQ method.</returns>
public static QueryableMethodKind? GetQueryableMethod(MethodCallExpression call) =>
call?.Method.DeclaringType is { } declaringType
&& (declaringType == WellKnownTypes.Queryable || declaringType == WellKnownTypes.Enumerable)
&& QueryableMethodKindFromName.TryGetValue(call.Method.Name, out var v)
? v
: null;
public static QueryableMethodKind? GetQueryableMethod(MethodCallExpression call)
{
if (call?.Method is { } method) {
var declaringType = method.DeclaringType;
return (declaringType == WellKnownTypes.Queryable || declaringType == WellKnownTypes.Enumerable)
&& QueryableMethodKindFromName.TryGetValue(method.Name, out var v)
? v
: null;
}

return null;
}
}
4 changes: 2 additions & 2 deletions Orm/Xtensive.Orm/Orm/Linq/Model/QueryFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ public static MethodCallExpression Select(Expression source, LambdaExpression pr
{
var sourceItemType = projection.Parameters[0].Type;
var resultItemType = projection.Body.Type;
var method = QueryableMethodInfo.Select.MakeGenericMethod(sourceItemType, resultItemType);
var method = QueryableMethodInfo.Select.CachedMakeGenericMethod(sourceItemType, resultItemType);
return Expression.Call(method, source, projection);
}
}
}
}
11 changes: 4 additions & 7 deletions Orm/Xtensive.Orm/Orm/Linq/Rewriters/AggregateOptimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
// Created by: Denis Krjuchkov
// Created: 2013.12.10

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Xtensive.Core;
Expand Down Expand Up @@ -170,11 +167,11 @@ protected override Expression VisitMethodCall(MethodCallExpression mc)
{
var methodKind = QueryableVisitor.GetQueryableMethod(mc);
if (methodKind==QueryableMethodKind.Select) {
var selectSource = mc.Arguments[0] as MethodCallExpression;
if (selectSource!=null) {
var mcArguments = mc.Arguments;
if (mcArguments[0] is MethodCallExpression selectSource) {
var sourceMethodKind = QueryableVisitor.GetQueryableMethod(selectSource);
if (sourceMethodKind==QueryableMethodKind.GroupBy) {
var projection = mc.Arguments[1].StripQuotes();
var projection = mcArguments[1].StripQuotes();
var newSelectSource = VisitGroupBy(selectSource, projection);
if (newSelectSource!=selectSource)
return QueryFactory.Select(newSelectSource, projection);
Expand All @@ -195,7 +192,7 @@ private MethodCallExpression VisitGroupBy(MethodCallExpression groupByCall, Lamb
var projection = groupBy.ResultSelector ?? selectProjection;
if (projection!=null) {
var referenceFieldAccessors = AggregateProjectionFinder.Execute(projection)
.Select(ReferenceFieldAccessExtractor.Execute)
.Select(static o => ReferenceFieldAccessExtractor.Execute(o))
.Where(item => item!=null)
.ToList();
if (referenceFieldAccessors.Count > 0) {
Expand Down