Skip to content

Commit 8d596b4

Browse files
committed
Prevent re-visiting expression in GetMeber for certain cases
In various cases it hurts translation, here is an attempt to skip a group of cases we can detect easily.
1 parent 5a5163b commit 8d596b4

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

Orm/Xtensive.Orm/Orm/Linq/Translator.Expressions.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1319,7 +1319,32 @@ private Expression GetMember(Expression expression, MemberInfo member, Expressio
13191319
var memberIndex = newExpression.Members.IndexOf(member);
13201320
if (memberIndex < 0)
13211321
throw new InvalidOperationException(string.Format(Strings.ExCouldNotGetMemberXFromExpression, member));
1322-
var argument = Visit(newExpression.Arguments[memberIndex]);
1322+
var argument = newExpression.Arguments[memberIndex];
1323+
var currentLambda = state.CurrentLambda;
1324+
if (!(currentLambda is null) && context.Bindings.TryGetValue(currentLambda.Parameters[0], out var projection)) {
1325+
// Here, we try to detect whether the expression has already visited, in such cases
1326+
// re-visiting it may cause issues. For instance, .OrderBy(x=>x.SomeField) translation
1327+
// gets projection of already visited source and substitutes parameter 'x' access with
1328+
// that projection. For now TranslatorState.ShouldOmitConvertToObject == true, is a marker
1329+
// of OrderBy visiting, because it is the only place that sets 'true' to the property,
1330+
// but we can't rely on it for future-proof solution.
1331+
1332+
// Knowing that parameter-to-projection binding happens when expression has visited,
1333+
// we assume this check is enough for certain cases, probably not for all of them.
1334+
// We can't deny visiting of the argument for all the cases because of chance to break
1335+
// some cases we could not imagine at the time of changes
1336+
switch (argument.NodeType) {
1337+
case ExpressionType.TypeAs:
1338+
case ExpressionType.Convert:
1339+
case ExpressionType.ConvertChecked:
1340+
if (argument.Type == typeof(object) && state.ShouldOmitConvertToObject)
1341+
argument = argument.StripCasts();
1342+
break;
1343+
}
1344+
}
1345+
else {
1346+
argument = Visit(argument);
1347+
}
13231348
return isMarker ? new MarkerExpression(argument, markerType) : argument;
13241349
}
13251350

0 commit comments

Comments
 (0)