@@ -20,6 +20,10 @@ public class RelationalQueryableMethodTranslatingExpressionVisitor : QueryableMe
20
20
21
21
private static readonly bool QuirkEnabled28727
22
22
= AppContext . TryGetSwitch ( "Microsoft.EntityFrameworkCore.Issue28727" , out var enabled ) && enabled ;
23
+ private static readonly bool QuirkEnabled30528
24
+ = AppContext . TryGetSwitch ( "Microsoft.EntityFrameworkCore.Issue30528" , out var enabled ) && enabled ;
25
+ private static readonly bool QuirkEnabled30572
26
+ = AppContext . TryGetSwitch ( "Microsoft.EntityFrameworkCore.Issue30572" , out var enabled ) && enabled ;
23
27
24
28
/// <summary>
25
29
/// Creates a new instance of the <see cref="QueryableMethodTranslatingExpressionVisitor" /> class.
@@ -1029,7 +1033,14 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
1029
1033
{
1030
1034
if ( source . ShaperExpression is IncludeExpression includeExpression )
1031
1035
{
1032
- source = source . UpdateShaperExpression ( PruneOwnedIncludes ( includeExpression ) ) ;
1036
+ if ( QuirkEnabled30572 )
1037
+ {
1038
+ source = source . UpdateShaperExpression ( PruneOwnedIncludes ( includeExpression ) ) ;
1039
+ }
1040
+ else
1041
+ {
1042
+ source = source . UpdateShaperExpression ( PruneIncludes ( includeExpression ) ) ;
1043
+ }
1033
1044
}
1034
1045
1035
1046
if ( source . ShaperExpression is not EntityShaperExpression entityShaperExpression )
@@ -1129,6 +1140,7 @@ static bool AreOtherNonOwnedEntityTypesInTheTable(IEntityType rootType, ITableBa
1129
1140
1130
1141
return TranslateExecuteDelete ( ( ShapedQueryExpression ) Visit ( newSource ) ) ;
1131
1142
1143
+ // Old quirked implementation for #30572
1132
1144
static Expression PruneOwnedIncludes ( IncludeExpression includeExpression )
1133
1145
{
1134
1146
if ( includeExpression . Navigation is ISkipNavigation
@@ -1163,6 +1175,16 @@ static Expression PruneOwnedIncludes(IncludeExpression includeExpression)
1163
1175
ShapedQueryExpression source ,
1164
1176
LambdaExpression setPropertyCalls )
1165
1177
{
1178
+ if ( ! QuirkEnabled30528 )
1179
+ {
1180
+ // Our source may have IncludeExpressions because of owned entities or auto-include; unwrap these, as they're meaningless for
1181
+ // ExecuteUpdate's lambdas. Note that we don't currently support updates across tables.
1182
+ if ( source . ShaperExpression is IncludeExpression includeExpression )
1183
+ {
1184
+ source = source . UpdateShaperExpression ( PruneIncludes ( includeExpression ) ) ;
1185
+ }
1186
+ }
1187
+
1166
1188
var propertyValueLambdaExpressions = new List < ( LambdaExpression , Expression ) > ( ) ;
1167
1189
PopulateSetPropertyCalls ( setPropertyCalls . Body , propertyValueLambdaExpressions , setPropertyCalls . Parameters [ 0 ] ) ;
1168
1190
if ( TranslationErrorDetails != null )
@@ -1386,7 +1408,6 @@ when methodCallExpression.Method.IsGenericMethod
1386
1408
&& methodCallExpression . Method . Name == nameof ( SetPropertyCalls < int > . SetProperty )
1387
1409
&& methodCallExpression . Method . DeclaringType ! . IsGenericType
1388
1410
&& methodCallExpression . Method . DeclaringType . GetGenericTypeDefinition ( ) == typeof ( SetPropertyCalls < > ) :
1389
-
1390
1411
list . Add ( ( ( LambdaExpression ) methodCallExpression . Arguments [ 0 ] , methodCallExpression . Arguments [ 1 ] ) ) ;
1391
1412
1392
1413
PopulateSetPropertyCalls ( methodCallExpression . Object ! , list , parameter ) ;
@@ -1400,8 +1421,8 @@ when methodCallExpression.Method.IsGenericMethod
1400
1421
}
1401
1422
1402
1423
// For property setter selectors in ExecuteUpdate, we support only simple member access, EF.Function, etc.
1403
- // We also unwrap casts to interface/base class (#29618), as well as IncludeExpressions (which occur when the target entity has
1404
- // owned entities, #28727).
1424
+ // We also unwrap casts to interface/base class (#29618). Note that owned IncludeExpressions have already been pruned from the
1425
+ // source before remapping the lambda ( #28727).
1405
1426
static bool TryProcessPropertyAccess (
1406
1427
IModel model ,
1407
1428
ref Expression expression ,
@@ -1449,9 +1470,12 @@ static Expression Unwrap(Expression expression)
1449
1470
{
1450
1471
expression = expression . UnwrapTypeConversion ( out _ ) ;
1451
1472
1452
- while ( expression is IncludeExpression includeExpression )
1473
+ if ( QuirkEnabled30528 )
1453
1474
{
1454
- expression = includeExpression . EntityExpression ;
1475
+ while ( expression is IncludeExpression includeExpression )
1476
+ {
1477
+ expression = includeExpression . EntityExpression ;
1478
+ }
1455
1479
}
1456
1480
1457
1481
return expression ;
@@ -1660,6 +1684,18 @@ private Expression RemapLambdaBody(ShapedQueryExpression shapedQueryExpression,
1660
1684
private Expression ExpandSharedTypeEntities ( SelectExpression selectExpression , Expression lambdaBody )
1661
1685
=> _sharedTypeEntityExpandingExpressionVisitor . Expand ( selectExpression , lambdaBody ) ;
1662
1686
1687
+ private static Expression PruneIncludes ( IncludeExpression includeExpression )
1688
+ {
1689
+ if ( includeExpression . Navigation is ISkipNavigation or not INavigation )
1690
+ {
1691
+ return includeExpression ;
1692
+ }
1693
+
1694
+ return includeExpression . EntityExpression is IncludeExpression innerIncludeExpression
1695
+ ? PruneIncludes ( innerIncludeExpression )
1696
+ : includeExpression . EntityExpression ;
1697
+ }
1698
+
1663
1699
private sealed class SharedTypeEntityExpandingExpressionVisitor : ExpressionVisitor
1664
1700
{
1665
1701
private readonly RelationalSqlTranslatingExpressionVisitor _sqlTranslator ;
0 commit comments