diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosPropertyExtensions.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosPropertyExtensions.cs
index 331e414bce5..98ead684f5e 100644
--- a/src/EFCore.Cosmos/Metadata/Internal/CosmosPropertyExtensions.cs
+++ b/src/EFCore.Cosmos/Metadata/Internal/CosmosPropertyExtensions.cs
@@ -23,7 +23,7 @@ public static bool IsOrdinalKeyProperty(this IReadOnlyProperty property)
(property.DeclaringType as IEntityType)?.IsOwned() == true, $"Expected {property.DeclaringType.DisplayName()} to be owned.");
Check.DebugAssert(property.GetJsonPropertyName().Length == 0, $"Expected {property.Name} to be non-persisted.");
- return property.FindContainingPrimaryKey() is IReadOnlyKey { Properties.Count: > 1 }
+ return property.FindContainingPrimaryKey() is { Properties.Count: > 1 }
&& !property.IsForeignKey()
&& property.ClrType == typeof(int)
&& (property.ValueGenerated & ValueGenerated.OnAdd) != 0;
diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs
index 5367a3eefc6..69e5153404b 100644
--- a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs
+++ b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs
@@ -52,38 +52,19 @@ public SqlExpressionFactory(ITypeMappingSource typeMappingSource, IModel model)
///
[return: NotNullIfNotNull("sqlExpression")]
public virtual SqlExpression? ApplyTypeMapping(SqlExpression? sqlExpression, CoreTypeMapping? typeMapping)
- {
- if (sqlExpression is not { TypeMapping: null })
- {
- return sqlExpression;
- }
-
-#pragma warning disable IDE0066 // Convert switch statement to expression
- switch (sqlExpression)
-#pragma warning restore IDE0066 // Convert switch statement to expression
+ => sqlExpression switch
{
- case SqlConditionalExpression sqlConditionalExpression:
- return ApplyTypeMappingOnSqlConditional(sqlConditionalExpression, typeMapping);
-
- case SqlBinaryExpression sqlBinaryExpression:
- return ApplyTypeMappingOnSqlBinary(sqlBinaryExpression, typeMapping);
-
- case SqlUnaryExpression sqlUnaryExpression:
- return ApplyTypeMappingOnSqlUnary(sqlUnaryExpression, typeMapping);
+ null or { TypeMapping: not null } => sqlExpression,
- case SqlConstantExpression sqlConstantExpression:
- return sqlConstantExpression.ApplyTypeMapping(typeMapping);
+ SqlConditionalExpression sqlConditionalExpression => ApplyTypeMappingOnSqlConditional(sqlConditionalExpression, typeMapping),
+ SqlBinaryExpression sqlBinaryExpression => ApplyTypeMappingOnSqlBinary(sqlBinaryExpression, typeMapping),
+ SqlUnaryExpression sqlUnaryExpression => ApplyTypeMappingOnSqlUnary(sqlUnaryExpression, typeMapping),
+ SqlConstantExpression sqlConstantExpression => sqlConstantExpression.ApplyTypeMapping(typeMapping),
+ SqlParameterExpression sqlParameterExpression => sqlParameterExpression.ApplyTypeMapping(typeMapping),
+ SqlFunctionExpression sqlFunctionExpression => sqlFunctionExpression.ApplyTypeMapping(typeMapping),
- case SqlParameterExpression sqlParameterExpression:
- return sqlParameterExpression.ApplyTypeMapping(typeMapping);
-
- case SqlFunctionExpression sqlFunctionExpression:
- return sqlFunctionExpression.ApplyTypeMapping(typeMapping);
-
- default:
- return sqlExpression;
- }
- }
+ _ => sqlExpression
+ };
private SqlExpression ApplyTypeMappingOnSqlConditional(
SqlConditionalExpression sqlConditionalExpression,
diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs
index c0cfebbde1b..bc86bdd78c2 100644
--- a/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs
+++ b/src/EFCore.Relational/Metadata/Internal/RelationalPropertyExtensions.cs
@@ -28,7 +28,7 @@ public static class RelationalPropertyExtensions
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public static bool IsOrdinalKeyProperty(this IReadOnlyProperty property)
- => property.FindContainingPrimaryKey() is IReadOnlyKey { Properties.Count: > 1 }
+ => property.FindContainingPrimaryKey() is { Properties.Count: > 1 }
&& !property.IsForeignKey()
&& property.ClrType == typeof(int)
&& property.GetJsonPropertyName() == null;
diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
index 89f0adf385f..2fd2e54731c 100644
--- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
@@ -494,13 +494,13 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent
=> TranslateAggregateWithSelector(source, selector, QueryableMethods.GetAverageWithoutSelector, throwWhenEmpty: true, resultType);
///
- protected override ShapedQueryExpression? TranslateCast(ShapedQueryExpression source, Type resultType)
+ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression source, Type resultType)
=> source.ShaperExpression.Type != resultType
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, resultType))
: source;
///
- protected override ShapedQueryExpression? TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2)
+ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2)
{
((SelectExpression)source1.QueryExpression).ApplyUnion((SelectExpression)source2.QueryExpression, distinct: false);
@@ -598,7 +598,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent
}
///
- protected override ShapedQueryExpression? TranslateDistinct(ShapedQueryExpression source)
+ protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source)
{
var selectExpression = (SelectExpression)source.QueryExpression;
if (selectExpression.Orderings.Count > 0
@@ -637,7 +637,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent
}
///
- protected override ShapedQueryExpression? TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2)
+ protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2)
{
((SelectExpression)source1.QueryExpression).ApplyExcept((SelectExpression)source2.QueryExpression, distinct: true);
@@ -797,7 +797,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent
=> null;
///
- protected override ShapedQueryExpression? TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2)
+ protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2)
{
((SelectExpression)source1.QueryExpression).ApplyIntersect((SelectExpression)source2.QueryExpression, distinct: true);
@@ -1230,7 +1230,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
}
///
- protected override ShapedQueryExpression? TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2)
+ protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2)
{
((SelectExpression)source1.QueryExpression).ApplyUnion((SelectExpression)source2.QueryExpression, distinct: true);
@@ -1927,7 +1927,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
source = methodCallExpression.Arguments[0];
var selectMethodCallExpression = default(MethodCallExpression);
- if (source is MethodCallExpression { Method: MethodInfo { IsGenericMethod: true } } sourceMethodCall
+ if (source is MethodCallExpression { Method.IsGenericMethod: true } sourceMethodCall
&& sourceMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.Select)
{
selectMethodCallExpression = sourceMethodCall;
@@ -1935,7 +1935,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
}
var asQueryableMethodCallExpression = default(MethodCallExpression);
- if (source is MethodCallExpression { Method: MethodInfo { IsGenericMethod: true } } maybeAsQueryableMethodCall
+ if (source is MethodCallExpression { Method.IsGenericMethod: true } maybeAsQueryableMethodCall
&& maybeAsQueryableMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.AsQueryable)
{
asQueryableMethodCallExpression = maybeAsQueryableMethodCall;
@@ -1946,7 +1946,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
if (source is JsonQueryExpression jsonQueryExpression)
{
- var collectionIndexExpression = _sqlTranslator.Translate(methodCallExpression.Arguments[1]!);
+ var collectionIndexExpression = _sqlTranslator.Translate(methodCallExpression.Arguments[1]);
if (collectionIndexExpression == null)
{
// before we return from failed translation
@@ -1960,7 +1960,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
methodCallExpression);
}
- var newJsonQuery = jsonQueryExpression.BindCollectionElement(collectionIndexExpression!);
+ var newJsonQuery = jsonQueryExpression.BindCollectionElement(collectionIndexExpression);
var entityShaper = new RelationalEntityShaperExpression(
jsonQueryExpression.EntityType,
@@ -2021,56 +2021,56 @@ static Expression PrepareFailedTranslationResult(
static bool IsValidSelectorForJsonArrayElementAccess(Expression expression, JsonQueryExpression baselineJsonQuery)
{
- // JSON_QUERY($[0]).Property
- if (expression is MemberExpression
- {
- Expression: RelationalEntityShaperExpression { ValueBufferExpression: JsonQueryExpression memberJqe }
- }
- && JsonQueryExpressionIsRootedIn(memberJqe, baselineJsonQuery))
+ switch (expression)
{
- return true;
- }
-
- // MCNE(JSON_QUERY($[0].Collection))
- // MCNE(JSON_QUERY($[0].Collection).AsQueryable())
- // MCNE(JSON_QUERY($[0].Collection).Select(xx => xx.Includes())
- // MCNE(JSON_QUERY($[0].Collection).AsQueryable().Select(xx => xx.Includes())
- if (expression is MaterializeCollectionNavigationExpression mcne)
- {
- var subquery = mcne.Subquery;
- if (subquery is MethodCallExpression { Method: MethodInfo { IsGenericMethod: true } } selectMethodCall
- && selectMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.Select
- && selectMethodCall.Arguments[1].UnwrapLambdaFromQuote() is LambdaExpression selectorLambda
- && StripIncludes(selectorLambda.Body) == selectorLambda.Parameters[0])
+ // JSON_QUERY($[0]).Property
+ case MemberExpression
+ {
+ Expression: RelationalEntityShaperExpression { ValueBufferExpression: JsonQueryExpression memberJqe }
+ }
+ when JsonQueryExpressionIsRootedIn(memberJqe, baselineJsonQuery):
{
- subquery = selectMethodCall.Arguments[0];
+ return true;
}
- if (subquery is MethodCallExpression { Method: MethodInfo { IsGenericMethod: true } } asQueryableMethodCall
- && asQueryableMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.AsQueryable)
+ // MCNE(JSON_QUERY($[0].Collection))
+ // MCNE(JSON_QUERY($[0].Collection).AsQueryable())
+ // MCNE(JSON_QUERY($[0].Collection).Select(xx => xx.Includes())
+ // MCNE(JSON_QUERY($[0].Collection).AsQueryable().Select(xx => xx.Includes())
+ case MaterializeCollectionNavigationExpression { Subquery: var subquery }:
{
- subquery = asQueryableMethodCall.Arguments[0];
- }
+ if (subquery is MethodCallExpression { Method.IsGenericMethod: true } selectMethodCall
+ && selectMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.Select
+ && selectMethodCall.Arguments[1].UnwrapLambdaFromQuote() is LambdaExpression selectorLambda
+ && StripIncludes(selectorLambda.Body) == selectorLambda.Parameters[0])
+ {
+ subquery = selectMethodCall.Arguments[0];
+ }
- if (subquery is JsonQueryExpression subqueryJqe
- && JsonQueryExpressionIsRootedIn(subqueryJqe, baselineJsonQuery))
- {
- return true;
+ if (subquery is MethodCallExpression { Method.IsGenericMethod: true } asQueryableMethodCall
+ && asQueryableMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.AsQueryable)
+ {
+ subquery = asQueryableMethodCall.Arguments[0];
+ }
+
+ if (subquery is JsonQueryExpression subqueryJqe
+ && JsonQueryExpressionIsRootedIn(subqueryJqe, baselineJsonQuery))
+ {
+ return true;
+ }
+
+ goto default;
}
- }
- // JSON_QUERY($[0]).Includes()
- // JSON_QUERY($[0].Reference).Includes()
- // JSON_QUERY($[0])
- // JSON_QUERY($[0].Reference)
- expression = StripIncludes(expression);
- if (expression is RelationalEntityShaperExpression { ValueBufferExpression: JsonQueryExpression reseJqe }
- && JsonQueryExpressionIsRootedIn(reseJqe, baselineJsonQuery))
- {
- return true;
+ default:
+ // JSON_QUERY($[0]).Includes()
+ // JSON_QUERY($[0].Reference).Includes()
+ // JSON_QUERY($[0])
+ // JSON_QUERY($[0].Reference)
+ expression = StripIncludes(expression);
+ return expression is RelationalEntityShaperExpression { ValueBufferExpression: JsonQueryExpression reseJqe }
+ && JsonQueryExpressionIsRootedIn(reseJqe, baselineJsonQuery);
}
-
- return false;
}
static bool JsonQueryExpressionIsRootedIn(JsonQueryExpression expressionToTest, JsonQueryExpression root)
@@ -2324,20 +2324,6 @@ private static Expression AccessField(
string fieldName)
=> Expression.Field(targetExpression, transparentIdentifierType.GetTypeInfo().GetDeclaredField(fieldName)!);
- private static void HandleGroupByForAggregate(SelectExpression selectExpression, bool eraseProjection = false)
- {
- if (selectExpression.GroupBy.Count > 0)
- {
- if (eraseProjection)
- {
- // Erasing client projections erase projectionMapping projections too
- selectExpression.ReplaceProjection(new List());
- }
-
- selectExpression.PushdownIntoSubquery();
- }
- }
-
private static Expression MatchShaperNullabilityForSetOperation(Expression shaper1, Expression shaper2, bool makeNullable)
{
switch (shaper1)
diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs
index 9205bbab608..e2aefc6343d 100644
--- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs
+++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs
@@ -112,9 +112,7 @@ private static TValue ThrowReadValueException(
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static TValue ThrowExtractJsonPropertyException(
- Exception exception,
- IProperty property)
+ private static TValue ThrowExtractJsonPropertyException(Exception exception, IProperty property)
{
var entityType = property.DeclaringType.DisplayName();
var propertyName = property.Name;
diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
index 01aee509205..0bc92ae317b 100644
--- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
@@ -408,58 +408,64 @@ public LambdaExpression ProcessShaper(
protected override Expression VisitBinary(BinaryExpression binaryExpression)
{
- if (binaryExpression is { NodeType: ExpressionType.Assign, Left: ParameterExpression parameterExpression }
- && parameterExpression.Type == typeof(MaterializationContext))
+ switch (binaryExpression)
{
- var newExpression = (NewExpression)binaryExpression.Right;
-
- if (newExpression.Arguments[0] is ProjectionBindingExpression projectionBindingExpression)
+ case { NodeType: ExpressionType.Assign, Left: ParameterExpression parameterExpression }
+ when parameterExpression.Type == typeof(MaterializationContext):
{
- var propertyMap = (IDictionary)GetProjectionIndex(projectionBindingExpression);
- _materializationContextBindings[parameterExpression] = propertyMap;
- _entityTypeIdentifyingExpressionInfo[parameterExpression] =
- // If single entity type is being selected in hierarchy then we use the value directly else we store the offset to
- // read discriminator value.
- _singleEntityTypeDiscriminatorValues.TryGetValue(projectionBindingExpression, out var value)
- ? value
- : propertyMap.Values.Max() + 1;
-
- var updatedExpression = newExpression.Update(
- new[] { Constant(ValueBuffer.Empty), newExpression.Arguments[1] });
-
- return Assign(binaryExpression.Left, updatedExpression);
- }
+ var newExpression = (NewExpression)binaryExpression.Right;
- if (newExpression.Arguments[0] is ParameterExpression valueBufferParameter
- && _jsonValueBufferToJsonReaderDataAndKeyValuesParameterMapping.ContainsKey(valueBufferParameter))
- {
- _jsonMaterializationContextToJsonReaderDataAndKeyValuesParameterMapping[parameterExpression] =
- _jsonValueBufferToJsonReaderDataAndKeyValuesParameterMapping[valueBufferParameter];
+ if (newExpression.Arguments[0] is ProjectionBindingExpression projectionBindingExpression)
+ {
+ var propertyMap = (IDictionary)GetProjectionIndex(projectionBindingExpression);
+ _materializationContextBindings[parameterExpression] = propertyMap;
+ _entityTypeIdentifyingExpressionInfo[parameterExpression] =
+ // If single entity type is being selected in hierarchy then we use the value directly else we store the offset
+ // to read discriminator value.
+ _singleEntityTypeDiscriminatorValues.TryGetValue(projectionBindingExpression, out var value)
+ ? value
+ : propertyMap.Values.Max() + 1;
+
+ var updatedExpression = newExpression.Update(
+ new[] { Constant(ValueBuffer.Empty), newExpression.Arguments[1] });
+
+ return Assign(binaryExpression.Left, updatedExpression);
+ }
- var updatedExpression = newExpression.Update(
- new[] { Constant(ValueBuffer.Empty), newExpression.Arguments[1] });
+ if (newExpression.Arguments[0] is ParameterExpression valueBufferParameter
+ && _jsonValueBufferToJsonReaderDataAndKeyValuesParameterMapping.TryGetValue(
+ valueBufferParameter, out var mappedParameter))
+ {
+ _jsonMaterializationContextToJsonReaderDataAndKeyValuesParameterMapping[parameterExpression] = mappedParameter;
+
+ var updatedExpression = newExpression.Update(
+ new[] { Constant(ValueBuffer.Empty), newExpression.Arguments[1] });
+
+ return Assign(binaryExpression.Left, updatedExpression);
+ }
- return Assign(binaryExpression.Left, updatedExpression);
+ break;
}
- }
- if (binaryExpression is
+ case
{
NodeType: ExpressionType.Assign,
Left: MemberExpression { Member: FieldInfo { IsInitOnly: true } } memberExpression
- })
- {
- return memberExpression.Assign(Visit(binaryExpression.Right));
- }
+ }:
+ {
+ return memberExpression.Assign(Visit(binaryExpression.Right));
+ }
- // we only have mapping between MaterializationContext and JsonReaderData, but we use JsonReaderManager to extract JSON values
- // so we need to add mapping between JsonReaderData and JsonReaderManager parameter, so we know which parameter to use
- // when generating actual Get* method
- if (binaryExpression is { NodeType: ExpressionType.Assign, Left: ParameterExpression jsonReaderManagerParameter }
- && jsonReaderManagerParameter.Type == typeof(Utf8JsonReaderManager))
- {
- var jsonReaderDataParameter = (ParameterExpression)((NewExpression)binaryExpression.Right).Arguments[0];
- _jsonReaderDataToJsonReaderManagerParameterMapping[jsonReaderDataParameter] = jsonReaderManagerParameter;
+ // we only have mapping between MaterializationContext and JsonReaderData, but we use JsonReaderManager to extract JSON
+ // values so we need to add mapping between JsonReaderData and JsonReaderManager parameter, so we know which parameter to
+ // use when generating actual Get* method
+ case { NodeType: ExpressionType.Assign, Left: ParameterExpression jsonReaderManagerParameter }
+ when jsonReaderManagerParameter.Type == typeof(Utf8JsonReaderManager):
+ {
+ var jsonReaderDataParameter = (ParameterExpression)((NewExpression)binaryExpression.Right).Arguments[0];
+ _jsonReaderDataToJsonReaderManagerParameterMapping[jsonReaderDataParameter] = jsonReaderManagerParameter;
+ break;
+ }
}
return base.VisitBinary(binaryExpression);
@@ -1082,10 +1088,8 @@ Expression CompensateForCollectionMaterialization(ParameterExpression parameter,
Constant(_valuesArrayInitializers.Count - 1)),
resultType);
}
- else
- {
- return parameter;
- }
+
+ return parameter;
}
}
@@ -1099,9 +1103,10 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
var property = methodCallExpression.Arguments[2].GetConstantValue();
var mappingParameter = (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object!;
- if (_jsonMaterializationContextToJsonReaderDataAndKeyValuesParameterMapping.ContainsKey(mappingParameter))
+ if (_jsonMaterializationContextToJsonReaderDataAndKeyValuesParameterMapping.TryGetValue(
+ mappingParameter, out var mappedParameter))
{
- var (jsonReaderDataParameter, keyPropertyValuesParameter) = _jsonMaterializationContextToJsonReaderDataAndKeyValuesParameterMapping[mappingParameter];
+ var (jsonReaderDataParameter, keyPropertyValuesParameter) = mappedParameter;
if (property!.IsPrimaryKey())
{
@@ -1110,16 +1115,14 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
ObjectArrayIndexerPropertyInfo,
new[] { Constant(index) });
}
- else
- {
- var jsonReaderManagerParameter = _jsonReaderDataToJsonReaderManagerParameterMapping[jsonReaderDataParameter];
- var jsonReadPropertyValueExpression = CreateReadJsonPropertyValueExpression(jsonReaderManagerParameter, property);
+ var jsonReaderManagerParameter = _jsonReaderDataToJsonReaderManagerParameterMapping[jsonReaderDataParameter];
- return methodCallExpression.Type != jsonReadPropertyValueExpression.Type
- ? Convert(jsonReadPropertyValueExpression, methodCallExpression.Type)
- : jsonReadPropertyValueExpression;
- }
+ var jsonReadPropertyValueExpression = CreateReadJsonPropertyValueExpression(jsonReaderManagerParameter, property);
+
+ return methodCallExpression.Type != jsonReadPropertyValueExpression.Type
+ ? Convert(jsonReadPropertyValueExpression, methodCallExpression.Type)
+ : jsonReadPropertyValueExpression;
}
int projectionIndex;
@@ -1625,21 +1628,10 @@ protected override Expression VisitSwitch(SwitchExpression switchExpression)
_navigationVariableMap[innerShaperMapElement.Key] = propertyVariable;
- var moveNext = Call(
- managerVariable,
- Utf8JsonReaderManagerMoveNextMethod);
-
- var captureState = Call(
- managerVariable,
- Utf8JsonReaderManagerCaptureStateMethod);
-
- var assignment = Assign(
- propertyVariable,
- innerShaperMapElement.Value);
-
- var managerRecreation = Assign(
- managerVariable,
- New(JsonReaderManagerConstructor, _jsonReaderDataParameter));
+ var moveNext = Call(managerVariable, Utf8JsonReaderManagerMoveNextMethod);
+ var captureState = Call(managerVariable, Utf8JsonReaderManagerCaptureStateMethod);
+ var assignment = Assign(propertyVariable, innerShaperMapElement.Value);
+ var managerRecreation = Assign(managerVariable, New(JsonReaderManagerConstructor, _jsonReaderDataParameter));
readExpressions.Add(
Block(
@@ -1664,29 +1656,20 @@ protected override Expression VisitSwitch(SwitchExpression switchExpression)
}
var loopBody = Block(
- Assign(
- tokenTypeVariable,
- Call(
- managerVariable,
- Utf8JsonReaderManagerMoveNextMethod)),
+ Assign(tokenTypeVariable, Call(managerVariable, Utf8JsonReaderManagerMoveNextMethod)),
Switch(
tokenTypeVariable,
Block(
Call(
- Field(
- managerVariable,
- Utf8JsonReaderManagerCurrentReaderField),
+ Field(managerVariable, Utf8JsonReaderManagerCurrentReaderField),
Utf8JsonReaderTrySkipMethod),
Default(typeof(void))),
- new SwitchCase[]
- {
- SwitchCase(
- testExpression,
- Constant(JsonTokenType.PropertyName)),
- SwitchCase(
- Break(breakLabel),
- Constant(JsonTokenType.EndObject)),
- }));
+ SwitchCase(
+ testExpression,
+ Constant(JsonTokenType.PropertyName)),
+ SwitchCase(
+ Break(breakLabel),
+ Constant(JsonTokenType.EndObject))));
return (Loop(loopBody, breakLabel), propertyAssignmentMap);
}
@@ -1710,10 +1693,15 @@ protected override Expression VisitConditional(ConditionalExpression conditional
if (_isTracking
&& visited is ConditionalExpression
{
- Test: BinaryExpression { NodeType: ExpressionType.NotEqual, Left: ParameterExpression leftPrm, Right: DefaultExpression rightDefault } testBinaryExpression,
+ Test: BinaryExpression
+ {
+ NodeType: ExpressionType.NotEqual,
+ Left: ParameterExpression,
+ Right: DefaultExpression rightDefault
+ } testBinaryExpression,
IfTrue: BlockExpression ifTrueBlock,
IfFalse: BlockExpression ifFalseBlock
- } resultConditional
+ }
&& rightDefault.Type == typeof(InternalEntityEntry))
{
var entityAlreadyTrackedVariable = Variable(typeof(bool), "entityAlreadyTracked");
@@ -1742,7 +1730,9 @@ protected override Expression VisitConditional(ConditionalExpression conditional
resultBlockVariables.AddRange(ifFalseBlock.Variables.ToList());
- var instanceAssignment = ifFalseBlock.Expressions.OfType().Single(e => e is { NodeType: ExpressionType.Assign, Left: ParameterExpression instance, Right: BlockExpression } && instance.Type == _entityType.ClrType);
+ var instanceAssignment = ifFalseBlock.Expressions.OfType().Single(
+ e => e is { NodeType: ExpressionType.Assign, Left: ParameterExpression instance, Right: BlockExpression }
+ && instance.Type == _entityType.ClrType);
var instanceAssignmentBody = (BlockExpression)instanceAssignment.Right;
var newInstanceAssignmentVariables = instanceAssignmentBody.Variables.ToList();
@@ -1801,22 +1791,21 @@ protected override Expression VisitConditional(ConditionalExpression conditional
var newInstanceAssignmentBlock = Block(newInstanceAssignmentVariables, newInstanceAssignmentExpressions);
resultBlockExpressions.Add(
- Assign(
- instanceAssignment.Left,
- newInstanceAssignmentBlock));
+ Assign(instanceAssignment.Left, newInstanceAssignmentBlock));
var startTrackingAssignment = ifFalseBlock.Expressions
.OfType()
.Single(e => e is { NodeType: ExpressionType.Assign, Left: ParameterExpression instance, Right: ConditionalExpression } && instance.Type == typeof(InternalEntityEntry));
- var startTrackingExpression = IfThen(
- Not(
- OrElse(
- entityAlreadyTrackedVariable,
- ((ConditionalExpression)startTrackingAssignment.Right).Test)),
- Block(
- ((ConditionalExpression)startTrackingAssignment.Right).IfFalse,
- Default(typeof(void))));
+ var startTrackingExpression =
+ IfThen(
+ Not(
+ OrElse(
+ entityAlreadyTrackedVariable,
+ ((ConditionalExpression)startTrackingAssignment.Right).Test)),
+ Block(
+ ((ConditionalExpression)startTrackingAssignment.Right).IfFalse,
+ Default(typeof(void))));
resultBlockExpressions.Add(startTrackingExpression);
resultBlockExpressions.Add(Default(typeof(void)));
@@ -1915,9 +1904,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
var jsonReaderDataAssignment = Assign(
jsonReaderDataVariable,
Condition(
- Equal(
- jsonStreamVariable,
- Default(typeof(MemoryStream))),
+ Equal(jsonStreamVariable, Default(typeof(MemoryStream))),
Default(typeof(JsonReaderData)),
New(JsonReaderDataConstructor, jsonStreamVariable)));
@@ -1927,20 +1914,15 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
// jsonReaderManager.MoveNext();
// jsonReaderManager.CaptureState();
// }
- var jsonReaderManagerBlock = IfThen(
- NotEqual(
- jsonReaderDataVariable,
- Default(typeof(JsonReaderData))),
- Block(
- Assign(
- jsonReaderManagerVariable,
- New(JsonReaderManagerConstructor, jsonReaderDataVariable)),
- Call(
- jsonReaderManagerVariable,
- Utf8JsonReaderManagerMoveNextMethod),
- Call(
- jsonReaderManagerVariable,
- Utf8JsonReaderManagerCaptureStateMethod)));
+ var jsonReaderManagerBlock =
+ IfThen(
+ NotEqual(
+ jsonReaderDataVariable,
+ Default(typeof(JsonReaderData))),
+ Block(
+ Assign(jsonReaderManagerVariable, New(JsonReaderManagerConstructor, jsonReaderDataVariable)),
+ Call(jsonReaderManagerVariable, Utf8JsonReaderManagerMoveNextMethod),
+ Call(jsonReaderManagerVariable, Utf8JsonReaderManagerCaptureStateMethod)));
_variables.Add(jsonStreamVariable);
_variables.Add(jsonReaderDataVariable);
@@ -1962,6 +1944,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
Constant(constant + 1),
typeof(object));
break;
+
case { KeyProperty: IProperty keyProperty }:
// if key value has IProperty, it must be a PK of the owner
var projection = _selectExpression.Projection[keyAccessInfo.KeyProjectionIndex!.Value];
@@ -1975,6 +1958,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
keyProperty),
typeof(object));
break;
+
default:
// otherwise it must be non-constant array access and we stored its projection index
// extract the value from the projection (or the cache if we used it before)
@@ -2279,22 +2263,6 @@ private Expression CreateReadJsonPropertyValueExpression(
{
if (!property.IsNullable || converter.ConvertsNulls)
{
- // in case of null value we can't just use the JsonReader method, but rather check the current token type
- // if it's JsonTokenType.Null means value is null, only if it's not we are safe to read the value
- if (nullable)
- {
- resultExpression = Condition(
- Equal(
- Property(
- Field(
- jsonReaderManagerParameter,
- Utf8JsonReaderManagerCurrentReaderField),
- Utf8JsonReaderTokenTypeProperty),
- Constant(JsonTokenType.Null)),
- Default(providerClrType),
- resultExpression);
- }
-
resultExpression = Convert(
Call(jsonReaderWriterExpression, fromJsonMethod, jsonReaderManagerParameter),
providerClrType);
@@ -2330,10 +2298,8 @@ private Expression CreateReadJsonPropertyValueExpression(
resultExpression = Condition(
Equal(
Property(
- Field(
- jsonReaderManagerParameter,
- Utf8JsonReaderManagerCurrentReaderField),
- Utf8JsonReaderTokenTypeProperty),
+ Field(jsonReaderManagerParameter, Utf8JsonReaderManagerCurrentReaderField),
+ Utf8JsonReaderTokenTypeProperty),
Constant(JsonTokenType.Null)),
Default(property.ClrType),
resultExpression);
@@ -2354,9 +2320,7 @@ private Expression CreateReadJsonPropertyValueExpression(
resultExpression = Condition(
Equal(
Property(
- Field(
- jsonReaderManagerParameter,
- Utf8JsonReaderManagerCurrentReaderField),
+ Field(jsonReaderManagerParameter, Utf8JsonReaderManagerCurrentReaderField),
Utf8JsonReaderTokenTypeProperty),
Constant(JsonTokenType.Null)),
Default(property.ClrType),
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs
index be5829edd73..722eca989e2 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs
@@ -70,7 +70,7 @@ public virtual void ProcessEntityTypeAnnotationChanged(
if (skipLevelNavigation.DeclaringEntityType.IsTemporal()
&& skipLevelNavigation.Inverse is IConventionSkipNavigation inverse
&& inverse.DeclaringEntityType.IsTemporal()
- && skipLevelNavigation.JoinEntityType is IConventionEntityType { HasSharedClrType: true } joinEntityType
+ && skipLevelNavigation.JoinEntityType is { HasSharedClrType: true } joinEntityType
&& !joinEntityType.IsTemporal()
&& joinEntityType.GetConfigurationSource() == ConfigurationSource.Convention)
{
diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs
index c660f7d2600..e3b99f42894 100644
--- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs
+++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs
@@ -142,7 +142,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression)
///
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
{
- if (methodCallExpression is MethodCallExpression { Method: MethodInfo { IsGenericMethod: true } } genericMethodCall
+ if (methodCallExpression is { Method: { IsGenericMethod: true } } genericMethodCall
&& genericMethodCall.Method.GetGenericMethodDefinition() == EnumerableMethods.ElementAt
&& genericMethodCall.Arguments[0].Type == typeof(byte[]))
{
diff --git a/src/EFCore/Extensions/Internal/TypeExtensions.cs b/src/EFCore/Extensions/Internal/TypeExtensions.cs
index 066575aed08..c190e678a28 100644
--- a/src/EFCore/Extensions/Internal/TypeExtensions.cs
+++ b/src/EFCore/Extensions/Internal/TypeExtensions.cs
@@ -68,7 +68,7 @@ public static string GenerateParameterName(this Type type)
pi =>
pi.Name == defaultPropertyAttribute.MemberName
&& pi.IsIndexerProperty()
- && pi.SetMethod?.GetParameters() is ParameterInfo[] { Length: 2 } parameters
+ && pi.SetMethod?.GetParameters() is { Length: 2 } parameters
&& parameters[0].ParameterType == typeof(string));
}
}
diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
index 97fd4cd99e8..505884263cc 100644
--- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
+++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
@@ -3141,7 +3141,7 @@ public static InternalIndexBuilder DetachIndex(Index indexToDetach)
// TODO: Use convention batch to get the updated builder, see #15898
var principalBuilder = Metadata.IsInModel
? Metadata.Builder
- : ownership?.PrincipalEntityType.FindNavigation(ownership.PrincipalToDependent!.Name)?.TargetEntityType is EntityType
+ : ownership?.PrincipalEntityType.FindNavigation(ownership.PrincipalToDependent!.Name)?.TargetEntityType is
{
IsInModel: true
} target
diff --git a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs
index 82b21ae77cf..9819a0cd941 100644
--- a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs
+++ b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs
@@ -87,32 +87,32 @@ protected override Expression VisitExtension(Expression extensionExpression)
if (extensionExpression is ShapedQueryExpression shapedQueryExpression)
{
var serverEnumerable = VisitShapedQuery(shapedQueryExpression);
- switch (shapedQueryExpression.ResultCardinality)
+
+ return shapedQueryExpression.ResultCardinality switch
{
- case ResultCardinality.Enumerable:
- return serverEnumerable;
-
- case ResultCardinality.Single:
- return QueryCompilationContext.IsAsync
- ? Call(
- SingleAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()),
- serverEnumerable,
- _cancellationTokenParameter)
- : Call(
- EnumerableMethods.SingleWithoutPredicate.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()),
- serverEnumerable);
-
- case ResultCardinality.SingleOrDefault:
- return QueryCompilationContext.IsAsync
- ? Call(
- SingleOrDefaultAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()),
- serverEnumerable,
- _cancellationTokenParameter)
- : Call(
- EnumerableMethods.SingleOrDefaultWithoutPredicate.MakeGenericMethod(
- serverEnumerable.Type.GetSequenceType()),
- serverEnumerable);
- }
+ ResultCardinality.Enumerable => serverEnumerable,
+
+ ResultCardinality.Single => QueryCompilationContext.IsAsync
+ ? Call(
+ SingleAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()),
+ serverEnumerable,
+ _cancellationTokenParameter)
+ : Call(
+ EnumerableMethods.SingleWithoutPredicate.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()),
+ serverEnumerable),
+
+ ResultCardinality.SingleOrDefault => QueryCompilationContext.IsAsync
+ ? Call(
+ SingleOrDefaultAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()),
+ serverEnumerable,
+ _cancellationTokenParameter)
+ : Call(
+ EnumerableMethods.SingleOrDefaultWithoutPredicate.MakeGenericMethod(
+ serverEnumerable.Type.GetSequenceType()),
+ serverEnumerable),
+
+ _ => base.VisitExtension(extensionExpression)
+ };
}
return base.VisitExtension(extensionExpression);
@@ -356,9 +356,7 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres
New(
MaterializationContextConstructor,
entityShaperExpression.ValueBufferExpression,
- MakeMemberAccess(
- QueryCompilationContext.QueryContextParameter,
- DbContextMemberInfo))));
+ MakeMemberAccess(QueryCompilationContext.QueryContextParameter, DbContextMemberInfo))));
var valueBufferExpression = Call(materializationContextVariable, MaterializationContext.GetValueBufferMethod);
@@ -371,10 +369,7 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres
var instanceVariable = Variable(entityType.ClrType, "instance" + _currentEntityIndex);
variables.Add(instanceVariable);
- expressions.Add(
- Assign(
- instanceVariable,
- Constant(null, entityType.ClrType)));
+ expressions.Add(Assign(instanceVariable, Constant(null, entityType.ClrType)));
if (_queryStateManager
&& primaryKey != null)
@@ -406,13 +401,9 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres
IfThen(
Not(hasNullKeyVariable),
IfThenElse(
- NotEqual(
- entryVariable,
- Default(typeof(InternalEntityEntry))),
+ NotEqual(entryVariable, Default(typeof(InternalEntityEntry))),
Block(
- Assign(
- concreteEntityTypeVariable,
- MakeMemberAccess(entryVariable, EntityTypeMemberInfo)),
+ Assign(concreteEntityTypeVariable, MakeMemberAccess(entryVariable, EntityTypeMemberInfo)),
Assign(
instanceVariable, Convert(
MakeMemberAccess(entryVariable, EntityMemberInfo),
diff --git a/test/EFCore.Relational.Specification.Tests/Query/OperatorsProceduralQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/OperatorsProceduralQueryTestBase.cs
index 0aeb301009e..3f01f8007dc 100644
--- a/test/EFCore.Relational.Specification.Tests/Query/OperatorsProceduralQueryTestBase.cs
+++ b/test/EFCore.Relational.Specification.Tests/Query/OperatorsProceduralQueryTestBase.cs
@@ -677,7 +677,7 @@ public ResultExpressionProjectionRewriter(Expression resultExpression, Expressio
protected override Expression VisitNew(NewExpression newExpression)
{
- if (newExpression.Constructor is ConstructorInfo { DeclaringType: Type { IsGenericType: true } declaringType })
+ if (newExpression.Constructor is { DeclaringType: { IsGenericType: true } declaringType })
{
if (declaringType.GetGenericTypeDefinition() == typeof(OperatorDto1<,>))
{
diff --git a/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs
index ed5ebd3ad86..b94bbd02b31 100644
--- a/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs
+++ b/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs
@@ -74,6 +74,7 @@ public virtual Task Can_use_backwards_is_animal(bool async)
=> AssertQuery(
async,
// ReSharper disable once IsExpressionAlwaysTrue
+ // ReSharper disable once ConvertTypeCheckToNullCheck
ss => ss.Set().Where(a => a is Animal),
entryCount: 1);
diff --git a/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs
index b4304117daa..cfc37c23e2d 100644
--- a/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs
+++ b/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs
@@ -1776,6 +1776,7 @@ public virtual Task Count_after_client_projection(bool async)
=> AssertCount(
async,
ss => ss.Set()
+ // ReSharper disable once ConvertTypeCheckToNullCheck
.Select(o => new { o.OrderID, Customer = o.Customer is Customer ? new { o.Customer.ContactName } : null })
.Take(1));
diff --git a/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs
index 1c2c568ccce..320ddeaa8bd 100644
--- a/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs
+++ b/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs
@@ -1641,6 +1641,7 @@ public virtual Task Where_projection(bool async)
public virtual Task Where_Is_on_same_type(bool async)
=> AssertQuery(
async,
+ // ReSharper disable once ConvertTypeCheckToNullCheck
ss => ss.Set().Where(c => c is Customer),
entryCount: 91);
@@ -1760,6 +1761,8 @@ public virtual Task Decimal_cast_to_double_works(bool async)
public virtual Task Where_is_conditional(bool async)
=> AssertQuery(
async,
+ // ReSharper disable once ConvertTypeCheckToNullCheck
+ // ReSharper disable once SimplifyConditionalTernaryExpression
ss => ss.Set().Where(p => p is Product ? false : true));
[ConditionalTheory]
diff --git a/test/EFCore.Specification.Tests/TestUtilities/ExpectedQueryRewritingVisitor.cs b/test/EFCore.Specification.Tests/TestUtilities/ExpectedQueryRewritingVisitor.cs
index 8baebd92a27..29b9aa43db5 100644
--- a/test/EFCore.Specification.Tests/TestUtilities/ExpectedQueryRewritingVisitor.cs
+++ b/test/EFCore.Specification.Tests/TestUtilities/ExpectedQueryRewritingVisitor.cs
@@ -246,7 +246,7 @@ private Expression TryConvertEFPropertyToMemberAccess(Expression expression)
var methodInfo = _getShadowPropertyValueMethodInfo.MakeGenericMethod(caller.Type, methodCallExpression.Type);
result = Expression.Call(methodInfo, caller, Expression.Constant(shadowPropertyMapping));
}
- else if (caller.Type.GetMembers().SingleOrDefault(m => m.Name == propertyName) is MemberInfo)
+ else if (caller.Type.GetMembers().SingleOrDefault(m => m.Name == propertyName) is not null)
{
result = Expression.Property(caller, propertyName);
}