diff --git a/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs b/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs index ad230acc93f..f72a15f02cb 100644 --- a/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { /// @@ -55,7 +57,7 @@ public EntityProjectionExpression( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override Type Type - => EntityType.ClrType; + => EntityType.ClrType!; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -137,7 +139,7 @@ public virtual void AddNavigationBinding([NotNull] INavigation navigation, [NotN /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual EntityShaperExpression BindNavigation([NotNull] INavigation navigation) + public virtual EntityShaperExpression? BindNavigation([NotNull] INavigation navigation) { if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index 16af3723528..77e11725141 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -17,8 +17,11 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; using ExpressionExtensions = Microsoft.EntityFrameworkCore.Infrastructure.ExpressionExtensions; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { /// @@ -90,7 +93,7 @@ public InMemoryExpressionTranslatingExpressionVisitor( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual string TranslationErrorDetails { get; private set; } + public virtual string? TranslationErrorDetails { get; private set; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -118,7 +121,7 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Expression Translate([NotNull] Expression expression) + public virtual Expression? Translate([NotNull] Expression expression) { Check.NotNull(expression, nameof(expression)); @@ -127,7 +130,7 @@ public virtual Expression Translate([NotNull] Expression expression) return TranslateInternal(expression); } - private Expression TranslateInternal(Expression expression) + private Expression? TranslateInternal(Expression expression) { var result = Visit(expression); @@ -142,7 +145,7 @@ private Expression TranslateInternal(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitBinary(BinaryExpression binaryExpression) + protected override Expression? VisitBinary(BinaryExpression binaryExpression) { Check.NotNull(binaryExpression, nameof(binaryExpression)); @@ -163,12 +166,12 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) } if ((binaryExpression.NodeType == ExpressionType.Equal - || binaryExpression.NodeType == ExpressionType.NotEqual) + || binaryExpression.NodeType == ExpressionType.NotEqual) // Visited expression could be null, We need to pass MemberInitExpression && TryRewriteEntityEquality( binaryExpression.NodeType, - newLeft ?? binaryExpression.Left, - newRight ?? binaryExpression.Right, + newLeft, + newRight, equalsMethod: false, out var result)) { @@ -222,7 +225,7 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitConditional(ConditionalExpression conditionalExpression) + protected override Expression? VisitConditional(ConditionalExpression conditionalExpression) { Check.NotNull(conditionalExpression, nameof(conditionalExpression)); @@ -258,7 +261,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitExtension(Expression extensionExpression) + protected override Expression? VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); @@ -294,7 +297,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitInvocation(InvocationExpression invocationExpression) + protected override Expression? VisitInvocation(InvocationExpression invocationExpression) => null; /// @@ -303,7 +306,7 @@ protected override Expression VisitInvocation(InvocationExpression invocationExp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitLambda(Expression lambdaExpression) + protected override Expression? VisitLambda(Expression lambdaExpression) => null; /// @@ -312,7 +315,7 @@ protected override Expression VisitLambda(Expression lambdaExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitListInit(ListInitExpression listInitExpression) + protected override Expression? VisitListInit(ListInitExpression listInitExpression) => null; /// @@ -321,7 +324,7 @@ protected override Expression VisitListInit(ListInitExpression listInitExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitMember(MemberExpression memberExpression) + protected override Expression? VisitMember(MemberExpression memberExpression) { Check.NotNull(memberExpression, nameof(memberExpression)); @@ -364,7 +367,7 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override MemberAssignment VisitMemberAssignment(MemberAssignment memberAssignment) + protected override MemberAssignment? VisitMemberAssignment(MemberAssignment memberAssignment) { var expression = Visit(memberAssignment.Expression); if (expression == null) @@ -386,7 +389,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment membe /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) + protected override Expression? VisitMethodCall(MethodCallExpression methodCallExpression) { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); @@ -417,7 +420,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (methodCallExpression.Arguments[0].Type.TryGetElementType(typeof(IQueryable<>)) == null && Visit(methodCallExpression.Arguments[0]) is GroupingElementExpression groupingElementExpression) { - Expression result = null; + Expression? result = null; switch (methodCallExpression.Method.Name) { case nameof(Enumerable.Average): @@ -433,7 +436,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp result = expression == null ? null : Expression.Call( - EnumerableMethods.GetAverageWithoutSelector(expression.Type.TryGetSequenceType()), expression); + EnumerableMethods.GetAverageWithoutSelector(expression.Type.TryGetSequenceType()!), expression); break; } @@ -441,14 +444,16 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp { if (methodCallExpression.Arguments.Count == 2) { - groupingElementExpression = ApplyPredicate( + var temporaryGroupingElementExpression = ApplyPredicate( groupingElementExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); - if (groupingElementExpression == null) + if (temporaryGroupingElementExpression == null) { result = null; break; } + + groupingElementExpression = temporaryGroupingElementExpression; } var expression = ApplySelect(groupingElementExpression); @@ -473,14 +478,16 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp { if (methodCallExpression.Arguments.Count == 2) { - groupingElementExpression = ApplyPredicate( + var temporaryGroupingElementExpression = ApplyPredicate( groupingElementExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); - if (groupingElementExpression == null) + if (temporaryGroupingElementExpression == null) { result = null; break; } + + groupingElementExpression = temporaryGroupingElementExpression; } var expression = ApplySelect(groupingElementExpression); @@ -509,7 +516,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } else { - var type = expression.Type.TryGetSequenceType(); + var type = expression.Type.TryGetSequenceType()!; var aggregateMethod = EnumerableMethods.GetMaxWithoutSelector(type); if (aggregateMethod.IsGenericMethod) { @@ -538,7 +545,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } else { - var type = expression.Type.TryGetSequenceType(); + var type = expression.Type.TryGetSequenceType()!; var aggregateMethod = EnumerableMethods.GetMinWithoutSelector(type); if (aggregateMethod.IsGenericMethod) { @@ -568,7 +575,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp result = expression == null ? null : Expression.Call( - EnumerableMethods.GetSumWithoutSelector(expression.Type.TryGetSequenceType()), expression); + EnumerableMethods.GetSumWithoutSelector(expression.Type.TryGetSequenceType()!), expression); break; } @@ -583,7 +590,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return result ?? throw new InvalidOperationException(CoreStrings.TranslationFailed(methodCallExpression.Print())); - GroupingElementExpression ApplyPredicate(GroupingElementExpression groupingElement, LambdaExpression lambdaExpression) + GroupingElementExpression? ApplyPredicate(GroupingElementExpression groupingElement, LambdaExpression lambdaExpression) { var predicate = TranslateInternal(RemapLambda(groupingElement, lambdaExpression)); @@ -596,7 +603,7 @@ GroupingElementExpression ApplyPredicate(GroupingElementExpression groupingEleme Expression.Lambda(predicate, groupingElement.ValueBufferParameter))); } - Expression ApplySelect(GroupingElementExpression groupingElement) + Expression? ApplySelect(GroupingElementExpression groupingElement) { var selector = TranslateInternal(groupingElement.Selector); @@ -649,7 +656,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE var shaperExpression = subqueryTranslation.ShaperExpression; var innerExpression = shaperExpression; - Type convertedType = null; + Type? convertedType = null; if (shaperExpression is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert) { @@ -671,6 +678,12 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE return null; } + if (projectionBindingExpression.ProjectionMember == null) + { + // We don't lift scalar subquery with client eval + return null; + } + return ProcessSingleResultScalar( subquery.ServerQueryExpression, subquery.GetMappedProjection(projectionBindingExpression.ProjectionMember), @@ -699,7 +712,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE return Expression.Call(_inMemoryLikeMethodInfo, visitedArguments); } - Expression @object = null; + Expression? @object = null; Expression[] arguments; var method = methodCallExpression.Method; @@ -840,7 +853,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE // if object is nullable, add null safeguard before calling the function // we special-case Nullable<>.GetValueOrDefault, which doesn't need the safeguard if (methodCallExpression.Object != null - && @object.Type.IsNullableType() + && @object!.Type.IsNullableType() && methodCallExpression.Method.Name != nameof(Nullable.GetValueOrDefault)) { var result = (Expression)methodCallExpression.Update( @@ -865,7 +878,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitNew(NewExpression newExpression) + protected override Expression? VisitNew(NewExpression newExpression) { Check.NotNull(newExpression, nameof(newExpression)); @@ -895,7 +908,7 @@ protected override Expression VisitNew(NewExpression newExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) + protected override Expression? VisitNewArray(NewArrayExpression newArrayExpression) { Check.NotNull(newArrayExpression, nameof(newArrayExpression)); @@ -925,7 +938,7 @@ protected override Expression VisitNewArray(NewArrayExpression newArrayExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitParameter(ParameterExpression parameterExpression) + protected override Expression? VisitParameter(ParameterExpression parameterExpression) { Check.NotNull(parameterExpression, nameof(parameterExpression)); @@ -946,7 +959,7 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) + protected override Expression? VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); @@ -963,9 +976,11 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp var derivedType = entityType.GetDerivedTypes().SingleOrDefault(et => et.ClrType == typeBinaryExpression.TypeOperand); if (derivedType != null) { - var discriminatorProperty = entityType.GetDiscriminatorProperty(); + // All hierarchies have discriminator property + var discriminatorProperty = entityType.GetDiscriminatorProperty()!; var boundProperty = BindProperty(entityReferenceExpression, discriminatorProperty, discriminatorProperty.ClrType); - var valueComparer = discriminatorProperty.GetKeyValueComparer(); + // KeyValueComparer is not null at runtime + var valueComparer = discriminatorProperty.GetKeyValueComparer()!; var equals = valueComparer.ExtractEqualsBody( boundProperty, @@ -993,7 +1008,7 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitUnary(UnaryExpression unaryExpression) + protected override Expression? VisitUnary(UnaryExpression unaryExpression) { Check.NotNull(unaryExpression, nameof(unaryExpression)); @@ -1048,7 +1063,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) return result; } - private Expression TryBindMember(Expression source, MemberIdentity member, Type type) + private Expression? TryBindMember(Expression source, MemberIdentity member, Type type) { if (!(source is EntityReferenceExpression entityReferenceExpression)) { @@ -1074,7 +1089,7 @@ private Expression TryBindMember(Expression source, MemberIdentity member, Type return null; } - private Expression BindProperty(EntityReferenceExpression entityReferenceExpression, IProperty property, Type type) + private Expression? BindProperty(EntityReferenceExpression entityReferenceExpression, IProperty property, Type type) { if (entityReferenceExpression.ParameterEntity != null) { @@ -1110,7 +1125,7 @@ private Expression BindProperty(EntityReferenceExpression entityReferenceExpress else { // This has to be index map since entities cannot map to just integer index - var index = projectionBindingExpression.IndexMap[property]; + var index = projectionBindingExpression.IndexMap![property]; readValueExpression = inMemoryQueryExpression.Projection[index]; } @@ -1176,7 +1191,7 @@ private static Expression ConvertToNonNullable(Expression expression) ? Expression.Convert(expression, expression.Type.UnwrapNullableType()) : expression; - private IProperty FindProperty(Expression expression) + private IProperty? FindProperty(Expression expression) { if (expression.NodeType == ExpressionType.Convert && expression.Type.IsNullableType() @@ -1196,7 +1211,7 @@ private IProperty FindProperty(Expression expression) return null; } - private bool TryRewriteContainsEntity(Expression source, Expression item, out Expression result) + private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.NotNullWhen(true)] out Expression? result) { result = null; @@ -1251,7 +1266,7 @@ when methodCallExpression.Method.IsGenericMethod var newParameterName = $"{_runtimeParameterPrefix}" - + $"{parameterName.Substring(QueryCompilationContext.QueryParameterPrefix.Length)}_{property.Name}"; + + $"{parameterName[QueryCompilationContext.QueryParameterPrefix.Length..]}_{property.Name}"; rewrittenSource = _queryCompilationContext.RegisterRuntimeParameter(newParameterName, lambda); break; @@ -1269,7 +1284,8 @@ when methodCallExpression.Method.IsGenericMethod return true; } - private bool TryRewriteEntityEquality(ExpressionType nodeType, Expression left, Expression right, bool equalsMethod, out Expression result) + private bool TryRewriteEntityEquality( + ExpressionType nodeType, Expression left, Expression right, bool equalsMethod, [CA.NotNullWhen(true)] out Expression? result) { var leftEntityReference = left as EntityReferenceExpression; var rightEntityReference = right as EntityReferenceExpression; @@ -1284,7 +1300,7 @@ private bool TryRewriteEntityEquality(ExpressionType nodeType, Expression left, if (IsNullConstantExpression(left) || IsNullConstantExpression(right)) { - var nonNullEntityReference = IsNullConstantExpression(left) ? rightEntityReference : leftEntityReference; + var nonNullEntityReference = (IsNullConstantExpression(left) ? rightEntityReference : leftEntityReference)!; var entityType1 = nonNullEntityReference.EntityType; var primaryKeyProperties1 = entityType1.FindPrimaryKey()?.Properties; if (primaryKeyProperties1 == null) @@ -1376,7 +1392,7 @@ when methodCallExpression.Method.IsGenericMethod var newParameterName = $"{_runtimeParameterPrefix}" - + $"{parameterName.Substring(QueryCompilationContext.QueryParameterPrefix.Length)}_{property.Name}"; + + $"{parameterName[QueryCompilationContext.QueryParameterPrefix.Length..]}_{property.Name}"; return _queryCompilationContext.RegisterRuntimeParameter(newParameterName, lambda); @@ -1400,12 +1416,15 @@ when CanEvaluate(memberInitExpression): } } +#nullable disable + // Need unconstrainted nullable T private static T ParameterValueExtractor(QueryContext context, string baseParameterName, IProperty property) { var baseParameter = context.ParameterValues[baseParameterName]; return baseParameter == null ? (T)(object)null : (T)property.GetGetter().GetClrValue(baseParameter); } + // Need unconstrainted nullable TProperty private static List ParameterListValueExtractor( QueryContext context, string baseParameterName, @@ -1419,6 +1438,7 @@ private static List ParameterListValueExtractor( var getter = property.GetGetter(); return baseListParameter.Select(e => e != null ? (TProperty)getter.GetClrValue(e) : (TProperty)(object)null).ToList(); } +#nullable enable private static ConstantExpression GetValue(Expression expression) => Expression.Constant( @@ -1483,10 +1503,10 @@ private static bool IsNullConstantExpression(Expression expression) => expression is ConstantExpression constantExpression && constantExpression.Value == null; [DebuggerStepThrough] - private static bool TranslationFailed(Expression original, Expression translation) - => original != null && (translation == null || translation is EntityReferenceExpression); + private static bool TranslationFailed(Expression? original, Expression? translation) + => original != null && TranslationFailed(translation); - private static bool TranslationFailed(Expression translation) + private static bool TranslationFailed([CA.NotNullWhen(false)] Expression? translation) => translation == null || translation is EntityReferenceExpression; private static bool InMemoryLike(string matchExpression, string pattern, string escapeCharacter) @@ -1621,17 +1641,18 @@ private EntityReferenceExpression(EntityReferenceExpression entityReferenceExpre EntityType = entityType; } - public EntityShaperExpression ParameterEntity { get; } - public ShapedQueryExpression SubqueryEntity { get; } + public EntityShaperExpression? ParameterEntity { get; } + public ShapedQueryExpression? SubqueryEntity { get; } public IEntityType EntityType { get; } public override Type Type - => EntityType.ClrType; + // No shadow entities at runtime + => EntityType.ClrType!; public override ExpressionType NodeType => ExpressionType.Extension; - public Expression Convert(Type type) + public Expression? Convert(Type type) { if (type == typeof(object) // Ignore object conversion || type.IsAssignableFrom(Type)) // Ignore casting to base type/interface diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs index 0e1ae7ce05c..01ba22955e7 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { /// @@ -46,6 +48,7 @@ public InMemoryProjectionBindingExpressionVisitor( { _queryableMethodTranslatingExpressionVisitor = queryableMethodTranslatingExpressionVisitor; _expressionTranslatingExpressionVisitor = expressionTranslatingExpressionVisitor; + _queryExpression = null!; } /// @@ -75,11 +78,11 @@ public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpre } _queryExpression.ReplaceProjectionMapping(_projectionMapping); - _queryExpression = null; + _queryExpression = null!; _projectionMapping.Clear(); _projectionMembers.Clear(); - result = MatchTypes(result, expression.Type); + result = MatchTypes(result!, expression.Type); return result; } @@ -90,7 +93,7 @@ public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpre /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override Expression Visit(Expression expression) + public override Expression? Visit(Expression? expression) { if (expression == null) { @@ -120,9 +123,9 @@ public override Expression Visit(Expression expression) case MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression: return AddCollectionProjection( _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( - materializeCollectionNavigationExpression.Subquery), + materializeCollectionNavigationExpression.Subquery)!, materializeCollectionNavigationExpression.Navigation, - materializeCollectionNavigationExpression.Navigation.ClrType.TryGetSequenceType()); + materializeCollectionNavigationExpression.Navigation.ClrType.TryGetSequenceType()!); case MethodCallExpression methodCallExpression: { @@ -196,8 +199,8 @@ public override Expression Visit(Expression expression) /// protected override Expression VisitBinary(BinaryExpression binaryExpression) { - var left = MatchTypes(Visit(binaryExpression.Left), binaryExpression.Left.Type); - var right = MatchTypes(Visit(binaryExpression.Right), binaryExpression.Right.Type); + var left = MatchTypes(Visit(binaryExpression.Left)!, binaryExpression.Left.Type); + var right = MatchTypes(Visit(binaryExpression.Right)!, binaryExpression.Right.Type); return binaryExpression.Update(left, VisitAndConvert(binaryExpression.Conversion, "VisitBinary"), right); } @@ -210,9 +213,9 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) /// protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { - var test = Visit(conditionalExpression.Test); - var ifTrue = Visit(conditionalExpression.IfTrue); - var ifFalse = Visit(conditionalExpression.IfFalse); + var test = Visit(conditionalExpression.Test)!; + var ifTrue = Visit(conditionalExpression.IfTrue)!; + var ifFalse = Visit(conditionalExpression.IfFalse)!; if (test.Type == typeof(bool?)) { @@ -228,7 +231,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitExtension(Expression extensionExpression) + protected override Expression? VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); @@ -237,6 +240,12 @@ protected override Expression VisitExtension(Expression extensionExpression) EntityProjectionExpression entityProjectionExpression; if (entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression) { + if (projectionBindingExpression.ProjectionMember == null) + { + // We don't process binding with client projection + return null; + } + entityProjectionExpression = (EntityProjectionExpression)((InMemoryQueryExpression)projectionBindingExpression.QueryExpression) .GetMappedProjection(projectionBindingExpression.ProjectionMember); } @@ -274,7 +283,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override ElementInit VisitElementInit(ElementInit elementInit) - => elementInit.Update(elementInit.Arguments.Select(e => MatchTypes(Visit(e), e.Type))); + => elementInit.Update(elementInit.Arguments.Select(e => MatchTypes(Visit(e)!, e.Type))); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -311,10 +320,10 @@ protected override Expression VisitMember(MemberExpression memberExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override MemberAssignment VisitMemberAssignment(MemberAssignment memberAssignment) + protected override MemberAssignment? VisitMemberAssignment(MemberAssignment memberAssignment) { var expression = memberAssignment.Expression; - Expression visitedExpression; + Expression? visitedExpression; if (_clientEval) { visitedExpression = Visit(memberAssignment.Expression); @@ -333,7 +342,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment membe _projectionMembers.Pop(); } - visitedExpression = MatchTypes(visitedExpression, expression.Type); + visitedExpression = MatchTypes(visitedExpression!, expression.Type); return memberAssignment.Update(visitedExpression); } @@ -344,7 +353,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment membe /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) + protected override Expression? VisitMemberInit(MemberInitExpression memberInitExpression) { Check.NotNull(memberInitExpression, nameof(memberInitExpression)); @@ -385,7 +394,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp for (var i = 0; i < methodCallExpression.Arguments.Count; i++) { var argument = methodCallExpression.Arguments[i]; - arguments[i] = MatchTypes(Visit(argument), argument.Type); + arguments[i] = MatchTypes(Visit(argument)!, argument.Type); } Expression updatedMethodCallExpression = methodCallExpression.Update( @@ -416,7 +425,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitNew(NewExpression newExpression) + protected override Expression? VisitNew(NewExpression newExpression) { Check.NotNull(newExpression, nameof(newExpression)); @@ -435,7 +444,7 @@ protected override Expression VisitNew(NewExpression newExpression) for (var i = 0; i < newArguments.Length; i++) { var argument = newExpression.Arguments[i]; - Expression visitedArgument; + Expression? visitedArgument; if (_clientEval) { visitedArgument = Visit(argument); @@ -453,7 +462,7 @@ protected override Expression VisitNew(NewExpression newExpression) _projectionMembers.Pop(); } - newArguments[i] = MatchTypes(visitedArgument, argument.Type); + newArguments[i] = MatchTypes(visitedArgument!, argument.Type); } return newExpression.Update(newArguments); @@ -466,7 +475,7 @@ protected override Expression VisitNew(NewExpression newExpression) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) - => newArrayExpression.Update(newArrayExpression.Expressions.Select(e => MatchTypes(Visit(e), e.Type))); + => newArrayExpression.Update(newArrayExpression.Expressions.Select(e => MatchTypes(Visit(e)!, e.Type))); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -476,7 +485,7 @@ protected override Expression VisitNewArray(NewArrayExpression newArrayExpressio /// protected override Expression VisitUnary(UnaryExpression unaryExpression) { - var operand = Visit(unaryExpression.Operand); + var operand = Visit(unaryExpression.Operand)!; return (unaryExpression.NodeType == ExpressionType.Convert || unaryExpression.NodeType == ExpressionType.ConvertChecked) @@ -487,7 +496,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) private CollectionShaperExpression AddCollectionProjection( ShapedQueryExpression subquery, - INavigationBase navigation, + INavigationBase? navigation, Type elementType) => new CollectionShaperExpression( new ProjectionBindingExpression( diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.ResultEnumerable.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.ResultEnumerable.cs index 4f4f92e5610..fa2f2eb8585 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.ResultEnumerable.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.ResultEnumerable.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public partial class InMemoryQueryExpression diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index fb7a2a589c7..b0656bb5bd3 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -16,6 +16,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using ExpressionExtensions = Microsoft.EntityFrameworkCore.Infrastructure.ExpressionExtensions; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { /// @@ -40,7 +42,7 @@ private readonly IDictionary _projectionMapping = new Dictionary(); - private ParameterExpression _groupingParameter; + private ParameterExpression? _groupingParameter; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -98,6 +100,7 @@ public InMemoryQueryExpression([NotNull] IEntityType entityType) ServerQueryExpression = new InMemoryTableExpression(entityType); var readExpressionMap = new Dictionary(); var discriminatorProperty = entityType.GetDiscriminatorProperty(); + var keyValueComparer = discriminatorProperty?.GetKeyValueComparer(); foreach (var property in entityType.GetAllBaseTypesInclusive().SelectMany(et => et.GetDeclaredProperties())) { readExpressionMap[property] = CreateReadValueExpression(property.ClrType, property.GetIndex(), property); @@ -107,9 +110,9 @@ public InMemoryQueryExpression([NotNull] IEntityType entityType) { var entityCheck = derivedEntityType.GetConcreteDerivedTypesInclusive() .Select( - e => discriminatorProperty.GetKeyValueComparer().ExtractEqualsBody( - readExpressionMap[discriminatorProperty], - Constant(e.GetDiscriminatorValue(), discriminatorProperty.ClrType))) + e => keyValueComparer!.ExtractEqualsBody( + readExpressionMap[discriminatorProperty!], + Constant(e.GetDiscriminatorValue(), discriminatorProperty!.ClrType))) .Aggregate((l, r) => OrElse(l, r)); foreach (var property in derivedEntityType.GetDeclaredProperties()) @@ -436,7 +439,7 @@ public virtual void ApplyDefaultIfEmpty() _valueBufferSlots.Clear(); } - private static IPropertyBase InferPropertyFromInner(Expression expression) + private static IPropertyBase? InferPropertyFromInner(Expression expression) => expression is MethodCallExpression methodCallExpression && methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == ExpressionExtensions.ValueBufferTryReadValueMethod @@ -576,7 +579,7 @@ private Expression GetGroupingKey(Expression key, List groupingExpre } } - private Expression CreateReadValueExpression(Type type, int index, IPropertyBase property) + private Expression CreateReadValueExpression(Type type, int index, IPropertyBase? property) => _valueBufferParameter.CreateValueBufferReadValueExpression(type, index, property); /// diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index 489dcae9b15..ac691d0d4da 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -9,12 +9,13 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.InMemory.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { /// @@ -78,7 +79,7 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) + protected override Expression? VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Arguments.Count == 1 @@ -102,7 +103,8 @@ protected override ShapedQueryExpression CreateShapedQueryExpression(Type elemen { Check.NotNull(elementType, nameof(elementType)); - return CreateShapedQueryExpression(_model.FindEntityType(elementType)); + // Let it throw if null found. + return CreateShapedQueryExpression(_model.FindEntityType(elementType)!); } /// @@ -135,17 +137,18 @@ private static ShapedQueryExpression CreateShapedQueryExpressionStatic(IEntityTy /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); predicate = Expression.Lambda(Expression.Not(predicate.Body), predicate.Parameters); - source = TranslateWhere(source, predicate); - if (source == null) + var newSource = TranslateWhere(source, predicate); + if (newSource == null) { return null; } + source = newSource; var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; @@ -170,15 +173,16 @@ protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression sour /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateAny(ShapedQueryExpression source, LambdaExpression? predicate) { if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var newSource = TranslateWhere(source, predicate); + if (newSource == null) { return null; } + source = newSource; } var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; @@ -203,7 +207,7 @@ protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression sour /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression source, LambdaExpression selector, Type resultType) + protected override ShapedQueryExpression? TranslateAverage(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -217,7 +221,7 @@ protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression source, Type resultType) + protected override ShapedQueryExpression? TranslateCast(ShapedQueryExpression source, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -233,7 +237,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -247,18 +251,20 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression source, Expression item) + protected override ShapedQueryExpression? TranslateContains(ShapedQueryExpression source, Expression item) { Check.NotNull(source, nameof(source)); Check.NotNull(item, nameof(item)); var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - item = TranslateExpression(item, preserveType: true); - if (item == null) + var newItem = TranslateExpression(item, preserveType: true); + if (newItem == null) { return null; } + item = newItem; + inMemoryQueryExpression.UpdateServerQueryExpression( Expression.Call( EnumerableMethods.Contains.MakeGenericMethod(item.Type), @@ -278,17 +284,18 @@ protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateCount(ShapedQueryExpression source, LambdaExpression? predicate) { Check.NotNull(source, nameof(source)); if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var newSource = TranslateWhere(source, predicate); + if (newSource == null) { return null; } + source = newSource; } var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; @@ -313,7 +320,7 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue) + protected override ShapedQueryExpression? TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression? defaultValue) { Check.NotNull(source, nameof(source)); @@ -332,7 +339,7 @@ protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpr /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source) + protected override ShapedQueryExpression? TranslateDistinct(ShapedQueryExpression source) { Check.NotNull(source, nameof(source)); @@ -353,7 +360,7 @@ protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateElementAtOrDefault( + protected override ShapedQueryExpression? TranslateElementAtOrDefault( ShapedQueryExpression source, Expression index, bool returnDefault) @@ -370,7 +377,7 @@ protected override ShapedQueryExpression TranslateElementAtOrDefault( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -384,9 +391,9 @@ protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression s /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateFirstOrDefault( + protected override ShapedQueryExpression? TranslateFirstOrDefault( ShapedQueryExpression source, - LambdaExpression predicate, + LambdaExpression? predicate, Type returnType, bool returnDefault) { @@ -408,11 +415,11 @@ protected override ShapedQueryExpression TranslateFirstOrDefault( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateGroupBy( + protected override ShapedQueryExpression? TranslateGroupBy( ShapedQueryExpression source, LambdaExpression keySelector, - LambdaExpression elementSelector, - LambdaExpression resultSelector) + LambdaExpression? elementSelector, + LambdaExpression? resultSelector) { Check.NotNull(source, nameof(source)); Check.NotNull(keySelector, nameof(keySelector)); @@ -452,7 +459,7 @@ protected override ShapedQueryExpression TranslateGroupBy( return null; } - private Expression TranslateGroupingKey(Expression expression) + private Expression? TranslateGroupingKey(Expression expression) { switch (expression) { @@ -462,7 +469,7 @@ private Expression TranslateGroupingKey(Expression expression) return newExpression; } - var newArguments = new Expression[newExpression.Arguments.Count]; + var newArguments = new Expression?[newExpression.Arguments.Count]; for (var i = 0; i < newArguments.Length; i++) { newArguments[i] = TranslateGroupingKey(newExpression.Arguments[i]); @@ -475,7 +482,7 @@ private Expression TranslateGroupingKey(Expression expression) return newExpression.Update(newArguments); case MemberInitExpression memberInitExpression: - var updatedNewExpression = (NewExpression)TranslateGroupingKey(memberInitExpression.NewExpression); + var updatedNewExpression = (NewExpression?)TranslateGroupingKey(memberInitExpression.NewExpression); if (updatedNewExpression == null) { return null; @@ -515,7 +522,7 @@ private Expression TranslateGroupingKey(Expression expression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateGroupJoin( + protected override ShapedQueryExpression? TranslateGroupJoin( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, @@ -537,7 +544,7 @@ protected override ShapedQueryExpression TranslateGroupJoin( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -551,7 +558,7 @@ protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateJoin( + protected override ShapedQueryExpression? TranslateJoin( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, @@ -564,13 +571,14 @@ protected override ShapedQueryExpression TranslateJoin( Check.NotNull(innerKeySelector, nameof(innerKeySelector)); Check.NotNull(resultSelector, nameof(resultSelector)); - (outerKeySelector, innerKeySelector) = ProcessJoinKeySelector(outer, inner, outerKeySelector, innerKeySelector); + var (newOuterKeySelector, newInnerKeySelector) = ProcessJoinKeySelector(outer, inner, outerKeySelector, innerKeySelector); - if (outerKeySelector == null - || innerKeySelector == null) + if (newOuterKeySelector == null + || newInnerKeySelector == null) { return null; } + (outerKeySelector, innerKeySelector) = (newOuterKeySelector, newInnerKeySelector); var transparentIdentifierType = TransparentIdentifierFactory.Create( resultSelector.Parameters[0].Type, @@ -591,7 +599,7 @@ protected override ShapedQueryExpression TranslateJoin( #pragma warning restore CS0618 // Type or member is obsolete } - private (LambdaExpression OuterKeySelector, LambdaExpression InnerKeySelector) ProcessJoinKeySelector( + private (LambdaExpression? OuterKeySelector, LambdaExpression? InnerKeySelector) ProcessJoinKeySelector( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, @@ -616,7 +624,7 @@ protected override ShapedQueryExpression TranslateJoin( return AlignKeySelectorTypes(outerKeySelector, innerKeySelector); } - private static (Expression, Expression) DecomposeJoinCondition(Expression joinCondition) + private static (Expression?, Expression?) DecomposeJoinCondition(Expression? joinCondition) { var leftExpressions = new List(); var rightExpressions = new List(); @@ -630,17 +638,14 @@ private static (Expression, Expression) DecomposeJoinCondition(Expression joinCo // InMemory joins need to use AnonymousObject to perform correct key comparison for server side joins static Expression CreateAnonymousObject(List expressions) => Expression.New( -#pragma warning disable EF1001 // Internal EF Core API usage. - // #20565 AnonymousObject.AnonymousObjectCtor, -#pragma warning restore EF1001 // Internal EF Core API usage. Expression.NewArrayInit( typeof(object), expressions.Select(e => Expression.Convert(e, typeof(object))))); } private static bool ProcessJoinCondition( - Expression joinCondition, + Expression? joinCondition, List leftExpressions, List rightExpressions) { @@ -695,9 +700,9 @@ static bool IsConvertedToNullable(Expression outer, Expression inner) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateLastOrDefault( + protected override ShapedQueryExpression? TranslateLastOrDefault( ShapedQueryExpression source, - LambdaExpression predicate, + LambdaExpression? predicate, Type returnType, bool returnDefault) { @@ -719,7 +724,7 @@ protected override ShapedQueryExpression TranslateLastOrDefault( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateLeftJoin( + protected override ShapedQueryExpression? TranslateLeftJoin( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, @@ -732,14 +737,16 @@ protected override ShapedQueryExpression TranslateLeftJoin( Check.NotNull(innerKeySelector, nameof(innerKeySelector)); Check.NotNull(resultSelector, nameof(resultSelector)); - (outerKeySelector, innerKeySelector) = ProcessJoinKeySelector(outer, inner, outerKeySelector, innerKeySelector); + var (newOuterKeySelector, newInnerKeySelector) = ProcessJoinKeySelector(outer, inner, outerKeySelector, innerKeySelector); - if (outerKeySelector == null - || innerKeySelector == null) + if (newOuterKeySelector == null + || newInnerKeySelector == null) { return null; } + (outerKeySelector, innerKeySelector) = (newOuterKeySelector, newInnerKeySelector); + var transparentIdentifierType = TransparentIdentifierFactory.Create( resultSelector.Parameters[0].Type, resultSelector.Parameters[1].Type); @@ -765,17 +772,19 @@ protected override ShapedQueryExpression TranslateLeftJoin( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateLongCount(ShapedQueryExpression source, LambdaExpression? predicate) { Check.NotNull(source, nameof(source)); if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var newSource = TranslateWhere(source, predicate); + if (newSource == null) { return null; } + + source = newSource; } var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; @@ -801,9 +810,9 @@ protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateMax( + protected override ShapedQueryExpression? TranslateMax( ShapedQueryExpression source, - LambdaExpression selector, + LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); @@ -817,7 +826,7 @@ protected override ShapedQueryExpression TranslateMax( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression source, LambdaExpression selector, Type resultType) + protected override ShapedQueryExpression? TranslateMin(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); @@ -830,7 +839,7 @@ protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression sour /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression source, Type resultType) + protected override ShapedQueryExpression? TranslateOfType(ShapedQueryExpression source, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -845,12 +854,13 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s var parameterExpression = Expression.Parameter(entityShaperExpression.Type); var predicate = Expression.Lambda(Expression.TypeIs(parameterExpression, resultType), parameterExpression); - source = TranslateWhere(source, predicate); - if (source == null) + var newSource = TranslateWhere(source, predicate); + if (newSource == null) { // EntityType is not part of hierarchy return null; } + source = newSource; var baseType = entityType.GetAllBaseTypes().SingleOrDefault(et => et.ClrType == resultType); if (baseType != null) @@ -884,7 +894,7 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateOrderBy( + protected override ShapedQueryExpression? TranslateOrderBy( ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) @@ -894,11 +904,12 @@ protected override ShapedQueryExpression TranslateOrderBy( var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - keySelector = TranslateLambdaExpression(source, keySelector); - if (keySelector == null) + var newKeySelector = TranslateLambdaExpression(source, keySelector); + if (newKeySelector == null) { return null; } + keySelector = newKeySelector; var orderBy = ascending ? EnumerableMethods.OrderBy : EnumerableMethods.OrderByDescending; inMemoryQueryExpression.UpdateServerQueryExpression( @@ -916,7 +927,7 @@ protected override ShapedQueryExpression TranslateOrderBy( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateReverse(ShapedQueryExpression source) + protected override ShapedQueryExpression? TranslateReverse(ShapedQueryExpression source) { Check.NotNull(source, nameof(source)); @@ -967,7 +978,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateSelectMany( + protected override ShapedQueryExpression? TranslateSelectMany( ShapedQueryExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector) @@ -1037,7 +1048,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) + protected override ShapedQueryExpression? TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) { Check.NotNull(source, nameof(source)); Check.NotNull(selector, nameof(selector)); @@ -1055,9 +1066,9 @@ protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpressi /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateSingleOrDefault( + protected override ShapedQueryExpression? TranslateSingleOrDefault( ShapedQueryExpression source, - LambdaExpression predicate, + LambdaExpression? predicate, Type returnType, bool returnDefault) { @@ -1079,17 +1090,18 @@ protected override ShapedQueryExpression TranslateSingleOrDefault( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression source, Expression count) + protected override ShapedQueryExpression? TranslateSkip(ShapedQueryExpression source, Expression count) { Check.NotNull(source, nameof(source)); Check.NotNull(count, nameof(count)); var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - count = TranslateExpression(count); - if (count == null) + var newCount = TranslateExpression(count); + if (newCount == null) { return null; } + count = newCount; inMemoryQueryExpression.UpdateServerQueryExpression( Expression.Call( @@ -1106,7 +1118,7 @@ protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression sou /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); @@ -1120,7 +1132,7 @@ protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression source, LambdaExpression selector, Type resultType) + protected override ShapedQueryExpression? TranslateSum(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -1134,17 +1146,18 @@ protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression sour /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression source, Expression count) + protected override ShapedQueryExpression? TranslateTake(ShapedQueryExpression source, Expression count) { Check.NotNull(source, nameof(source)); Check.NotNull(count, nameof(count)); var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - count = TranslateExpression(count); - if (count == null) + var newCount = TranslateExpression(count); + if (newCount == null) { return null; } + count = newCount; inMemoryQueryExpression.UpdateServerQueryExpression( Expression.Call( @@ -1161,7 +1174,7 @@ protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression sou /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); @@ -1175,17 +1188,18 @@ protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) + protected override ShapedQueryExpression? TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { Check.NotNull(source, nameof(source)); Check.NotNull(keySelector, nameof(keySelector)); var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - keySelector = TranslateLambdaExpression(source, keySelector); - if (keySelector == null) + var newKeySelector = TranslateLambdaExpression(source, keySelector); + if (newKeySelector == null) { return null; } + keySelector = newKeySelector; inMemoryQueryExpression.UpdateServerQueryExpression( Expression.Call( @@ -1203,7 +1217,7 @@ protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression s /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -1217,17 +1231,18 @@ protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression so /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - predicate = TranslateLambdaExpression(source, predicate, preserveType: true); - if (predicate == null) + var newPredicate = TranslateLambdaExpression(source, predicate, preserveType: true); + if (newPredicate == null) { return null; } + predicate = newPredicate; inMemoryQueryExpression.UpdateServerQueryExpression( Expression.Call( @@ -1238,7 +1253,7 @@ protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression so return source; } - private Expression TranslateExpression(Expression expression, bool preserveType = false) + private Expression? TranslateExpression(Expression expression, bool preserveType = false) { var translation = _expressionTranslator.Translate(expression); if (translation == null && _expressionTranslator.TranslationErrorDetails != null) @@ -1259,7 +1274,7 @@ private Expression TranslateExpression(Expression expression, bool preserveType return translation; } - private LambdaExpression TranslateLambdaExpression( + private LambdaExpression? TranslateLambdaExpression( ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression, bool preserveType = false) @@ -1286,15 +1301,16 @@ internal Expression ExpandWeakEntities(InMemoryQueryExpression queryExpression, private sealed class WeakEntityExpandingExpressionVisitor : ExpressionVisitor { - private InMemoryQueryExpression _queryExpression; private readonly InMemoryExpressionTranslatingExpressionVisitor _expressionTranslator; + private InMemoryQueryExpression _queryExpression; public WeakEntityExpandingExpressionVisitor(InMemoryExpressionTranslatingExpressionVisitor expressionTranslator) { _expressionTranslator = expressionTranslator; + _queryExpression = null!; } - public string TranslationErrorDetails + public string? TranslationErrorDetails => _expressionTranslator.TranslationErrorDetails; public Expression Expand(InMemoryQueryExpression queryExpression, Expression lambdaBody) @@ -1347,7 +1363,7 @@ protected override Expression VisitExtension(Expression extensionExpression) : base.VisitExtension(extensionExpression); } - private Expression TryExpand(Expression source, MemberIdentity member) + private Expression? TryExpand(Expression source, MemberIdentity member) { source = source.UnwrapTypeConversion(out var convertedType); if (!(source is EntityShaperExpression entityShaperExpression)) @@ -1426,11 +1442,20 @@ private Expression TryExpand(Expression source, MemberIdentity member) return innerShapedQuery; } - var entityProjectionExpression - = (EntityProjectionExpression)(entityShaperExpression.ValueBufferExpression is - ProjectionBindingExpression projectionBindingExpression - ? _queryExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember) - : entityShaperExpression.ValueBufferExpression); + EntityProjectionExpression entityProjectionExpression; + if (entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression) + { + if (projectionBindingExpression.ProjectionMember == null) + { + throw new InvalidOperationException(); + } + entityProjectionExpression = (EntityProjectionExpression)_queryExpression.GetMappedProjection( + projectionBindingExpression.ProjectionMember); + } + else + { + entityProjectionExpression = (EntityProjectionExpression)entityShaperExpression.ValueBufferExpression; + } var innerShaper = entityProjectionExpression.BindNavigation(navigation); if (innerShaper == null) @@ -1466,9 +1491,9 @@ ProjectionBindingExpression projectionBindingExpression } } - private ShapedQueryExpression TranslateScalarAggregate( + private ShapedQueryExpression? TranslateScalarAggregate( ShapedQueryExpression source, - LambdaExpression selector, + LambdaExpression? selector, string methodName, Type returnType) { @@ -1507,9 +1532,9 @@ MethodInfo GetMethod() }; } - private ShapedQueryExpression TranslateSingleResultOperator( + private ShapedQueryExpression? TranslateSingleResultOperator( ShapedQueryExpression source, - LambdaExpression predicate, + LambdaExpression? predicate, Type returnType, MethodInfo method) { @@ -1517,11 +1542,12 @@ private ShapedQueryExpression TranslateSingleResultOperator( if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var newSource = TranslateWhere(source, predicate); + if (newSource == null) { return null; } + source = newSource; } inMemoryQueryExpression.UpdateServerQueryExpression( diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs index 1bab63556f8..06206af6b05 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public partial class InMemoryShapedQueryCompilingExpressionVisitor @@ -145,7 +147,7 @@ private static TResult MaterializeSingleResult( ValueBuffer valueBuffer, Func innerShaper) => valueBuffer.IsEmpty - ? default + ? default! : innerShaper(queryContext, valueBuffer); protected override Expression VisitExtension(Expression extensionExpression) @@ -155,9 +157,9 @@ protected override Expression VisitExtension(Expression extensionExpression) if (extensionExpression is IncludeExpression includeExpression) { var entityClrType = includeExpression.EntityExpression.Type; - var includingClrType = includeExpression.Navigation.DeclaringEntityType.ClrType; + var includingClrType = includeExpression.Navigation.DeclaringEntityType.ClrType!; var inverseNavigation = includeExpression.Navigation.Inverse; - var relatedEntityClrType = includeExpression.Navigation.TargetEntityType.ClrType; + var relatedEntityClrType = includeExpression.Navigation.TargetEntityType.ClrType!; if (includingClrType != entityClrType && includingClrType.IsAssignableFrom(entityClrType)) { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs index 75440650364..4aa12a7672d 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using ExpressionExtensions = Microsoft.EntityFrameworkCore.Infrastructure.ExpressionExtensions; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public partial class InMemoryShapedQueryCompilingExpressionVisitor @@ -65,7 +67,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == ExpressionExtensions.ValueBufferTryReadValueMethod) { - var property = (IProperty)((ConstantExpression)methodCallExpression.Arguments[2]).Value; + var property = (IProperty?)((ConstantExpression)methodCallExpression.Arguments[2]).Value; var (indexMap, valueBuffer) = _materializationContextBindings[ (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object]; @@ -76,7 +78,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return Expression.Call( methodCallExpression.Method, valueBuffer, - Expression.Constant(indexMap[property]), + Expression.Constant(indexMap[property!]), methodCallExpression.Arguments[2]); } @@ -105,7 +107,7 @@ protected override Expression VisitExtension(Expression extensionExpression) return base.VisitExtension(extensionExpression); } - private IPropertyBase InferPropertyFromInner(Expression expression) + private IPropertyBase? InferPropertyFromInner(Expression expression) { if (expression is MethodCallExpression methodCallExpression && methodCallExpression.Method.IsGenericMethod @@ -125,7 +127,7 @@ private object GetProjectionIndex( ? ((ConstantExpression)queryExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value : (projectionBindingExpression.Index != null ? (object)projectionBindingExpression.Index - : projectionBindingExpression.IndexMap); + : projectionBindingExpression.IndexMap!); } } } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.QueryingEnumerable.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.QueryingEnumerable.cs index 216ac490a36..5521bf2985b 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.QueryingEnumerable.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.QueryingEnumerable.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { /// @@ -61,7 +63,6 @@ public string ToQueryString() private sealed class Enumerator : IEnumerator, IAsyncEnumerator { - private IEnumerator _enumerator; private readonly QueryContext _queryContext; private readonly IEnumerable _innerEnumerable; private readonly Func _shaper; @@ -70,6 +71,8 @@ private sealed class Enumerator : IEnumerator, IAsyncEnumerator private readonly bool _standAloneStateManager; private readonly CancellationToken _cancellationToken; + private IEnumerator? _enumerator; + public Enumerator(QueryingEnumerable queryingEnumerable, CancellationToken cancellationToken = default) { _queryContext = queryingEnumerable._queryContext; @@ -79,12 +82,13 @@ public Enumerator(QueryingEnumerable queryingEnumerable, CancellationToken ca _queryLogger = queryingEnumerable._queryLogger; _standAloneStateManager = queryingEnumerable._standAloneStateManager; _cancellationToken = cancellationToken; + Current = default!; } public T Current { get; private set; } object IEnumerator.Current - => Current; + => Current!; public bool MoveNext() { @@ -136,7 +140,7 @@ private bool MoveNextHelper() Current = hasNext ? _shaper(_queryContext, _enumerator.Current) - : default; + : default!; return hasNext; } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs index c55301e6ea5..bf27e11648d 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public partial class InMemoryShapedQueryCompilingExpressionVisitor : ShapedQueryCompilingExpressionVisitor diff --git a/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs index 446ea91d876..435273fec98 100644 --- a/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { /// @@ -17,7 +19,7 @@ namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal /// public class ShaperExpressionProcessingExpressionVisitor : ExpressionVisitor { - private readonly InMemoryQueryExpression _queryExpression; + private readonly InMemoryQueryExpression? _queryExpression; private readonly ParameterExpression _valueBufferParameter; private readonly IDictionary _mapping = new Dictionary(); @@ -31,7 +33,7 @@ public class ShaperExpressionProcessingExpressionVisitor : ExpressionVisitor /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public ShaperExpressionProcessingExpressionVisitor( - [CanBeNull] InMemoryQueryExpression queryExpression, + [CanBeNull] InMemoryQueryExpression? queryExpression, [NotNull] ParameterExpression valueBufferParameter) { _queryExpression = queryExpression; diff --git a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs index 852149dcf4a..019bb3f0bb4 100644 --- a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs @@ -164,7 +164,7 @@ private static FromSqlQueryRootExpression GenerateFromSqlQueryRoot( } return new FromSqlQueryRootExpression( - queryRootExpression.QueryProvider, + queryRootExpression.QueryProvider!, entityType, sql, Expression.Constant(arguments)); diff --git a/src/EFCore.Relational/Query/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs index 827ffff1a59..d61e44280c6 100644 --- a/src/EFCore.Relational/Query/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -51,7 +53,7 @@ public EntityProjectionExpression([NotNull] IEntityType entityType, [NotNull] Ta public EntityProjectionExpression( [NotNull] IEntityType entityType, [NotNull] IDictionary propertyExpressionMap, - [CanBeNull] SqlExpression discriminatorExpression = null) + [CanBeNull] SqlExpression? discriminatorExpression = null) { Check.NotNull(entityType, nameof(entityType)); Check.NotNull(propertyExpressionMap, nameof(propertyExpressionMap)); @@ -69,7 +71,7 @@ public EntityProjectionExpression( /// /// A to generate discriminator for entity type. /// - public virtual SqlExpression DiscriminatorExpression { get; } + public virtual SqlExpression? DiscriminatorExpression { get; } /// public sealed override ExpressionType NodeType @@ -77,7 +79,7 @@ public sealed override ExpressionType NodeType /// public override Type Type - => EntityType.ClrType; + => EntityType.ClrType!; /// protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -204,7 +206,7 @@ public virtual void AddNavigationBinding([NotNull] INavigation navigation, [NotN /// /// A navigation to bind. /// An entity shaper expression for the target entity type of the navigation. - public virtual EntityShaperExpression BindNavigation([NotNull] INavigation navigation) + public virtual EntityShaperExpression? BindNavigation([NotNull] INavigation navigation) { Check.NotNull(navigation, nameof(navigation)); diff --git a/src/EFCore.Relational/Query/ExpressionExtensions.cs b/src/EFCore.Relational/Query/ExpressionExtensions.cs index 7de532f65d1..c724a2dee23 100644 --- a/src/EFCore.Relational/Query/ExpressionExtensions.cs +++ b/src/EFCore.Relational/Query/ExpressionExtensions.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -25,7 +27,7 @@ public static class ExpressionExtensions /// /// Expressions to search for to find the type mapping. /// A relational type mapping inferred from the expressions. - public static RelationalTypeMapping InferTypeMapping([NotNull] params SqlExpression[] expressions) + public static RelationalTypeMapping? InferTypeMapping([NotNull] params SqlExpression[] expressions) { Check.NotNull(expressions, nameof(expressions)); diff --git a/src/EFCore.Relational/Query/IMemberTranslator.cs b/src/EFCore.Relational/Query/IMemberTranslator.cs index 8f8d93f660a..e3ab3bd2f27 100644 --- a/src/EFCore.Relational/Query/IMemberTranslator.cs +++ b/src/EFCore.Relational/Query/IMemberTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -29,8 +31,8 @@ public interface IMemberTranslator /// The return type from . /// The query logger to use. /// A SQL translation of the . - SqlExpression Translate( - [CanBeNull] SqlExpression instance, + SqlExpression? Translate( + [CanBeNull] SqlExpression? instance, [NotNull] MemberInfo member, [NotNull] Type returnType, [NotNull] IDiagnosticsLogger logger); diff --git a/src/EFCore.Relational/Query/IMemberTranslatorPlugin.cs b/src/EFCore.Relational/Query/IMemberTranslatorPlugin.cs index 7929bd72612..e8dc043a953 100644 --- a/src/EFCore.Relational/Query/IMemberTranslatorPlugin.cs +++ b/src/EFCore.Relational/Query/IMemberTranslatorPlugin.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs b/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs index e7472f9c75e..c0a975dcd2f 100644 --- a/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -31,8 +33,8 @@ public interface IMemberTranslatorProvider /// The return type from . /// The query logger to use. /// A SQL translation of the . - SqlExpression Translate( - [CanBeNull] SqlExpression instance, + SqlExpression? Translate( + [CanBeNull] SqlExpression? instance, [NotNull] MemberInfo member, [NotNull] Type returnType, [NotNull] IDiagnosticsLogger logger); diff --git a/src/EFCore.Relational/Query/IMethodCallTranslator.cs b/src/EFCore.Relational/Query/IMethodCallTranslator.cs index 0397812c0fc..200dd7be342 100644 --- a/src/EFCore.Relational/Query/IMethodCallTranslator.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -29,8 +31,8 @@ public interface IMethodCallTranslator /// SQL representations of . /// The query logger to use. /// A SQL translation of the . - SqlExpression Translate( - [CanBeNull] SqlExpression instance, + SqlExpression? Translate( + [CanBeNull] SqlExpression? instance, [NotNull] MethodInfo method, [NotNull] IReadOnlyList arguments, [NotNull] IDiagnosticsLogger logger); diff --git a/src/EFCore.Relational/Query/IMethodCallTranslatorPlugin.cs b/src/EFCore.Relational/Query/IMethodCallTranslatorPlugin.cs index 456373b8714..fe7e6162678 100644 --- a/src/EFCore.Relational/Query/IMethodCallTranslatorPlugin.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslatorPlugin.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs index ae1c8f1e503..9a6e13eb4ae 100644 --- a/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -33,9 +35,9 @@ public interface IMethodCallTranslatorProvider /// SQL representations of . /// The query logger to use. /// A SQL translation of the . - SqlExpression Translate( + SqlExpression? Translate( [NotNull] IModel model, - [CanBeNull] SqlExpression instance, + [CanBeNull] SqlExpression? instance, [NotNull] MethodInfo method, [NotNull] IReadOnlyList arguments, [NotNull] IDiagnosticsLogger logger); diff --git a/src/EFCore.Relational/Query/IQuerySqlGeneratorFactory.cs b/src/EFCore.Relational/Query/IQuerySqlGeneratorFactory.cs index 2f440247de3..6905131498b 100644 --- a/src/EFCore.Relational/Query/IQuerySqlGeneratorFactory.cs +++ b/src/EFCore.Relational/Query/IQuerySqlGeneratorFactory.cs @@ -3,6 +3,8 @@ using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/IRelationalParameterBasedSqlProcessorFactory.cs b/src/EFCore.Relational/Query/IRelationalParameterBasedSqlProcessorFactory.cs index 668ca42505f..5f39b4943e7 100644 --- a/src/EFCore.Relational/Query/IRelationalParameterBasedSqlProcessorFactory.cs +++ b/src/EFCore.Relational/Query/IRelationalParameterBasedSqlProcessorFactory.cs @@ -3,6 +3,8 @@ using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/IRelationalQueryStringFactory.cs b/src/EFCore.Relational/Query/IRelationalQueryStringFactory.cs index 7145a58aa37..e997de7e4e4 100644 --- a/src/EFCore.Relational/Query/IRelationalQueryStringFactory.cs +++ b/src/EFCore.Relational/Query/IRelationalQueryStringFactory.cs @@ -4,6 +4,8 @@ using System.Data.Common; using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs index 78911f96a93..9a3e6b04c1d 100644 --- a/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs index d233cc655d7..f5e6b167b9e 100644 --- a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs @@ -9,6 +9,9 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query { @@ -30,7 +33,7 @@ public interface ISqlExpressionFactory /// The object to get the mapping for. /// The type mapping to be used. [Obsolete("Use IRelationalTypeMappingSource directly.")] - RelationalTypeMapping GetTypeMappingForValue([CanBeNull] object value); + RelationalTypeMapping GetTypeMappingForValue([CanBeNull] object? value); /// /// Finds the type mapping for a given . @@ -46,14 +49,16 @@ public interface ISqlExpressionFactory /// A SQL expression to apply type mapping. /// A type mapping to apply. /// A SQL expression with given type mapping applied. - SqlExpression ApplyTypeMapping([CanBeNull] SqlExpression sqlExpression, [CanBeNull] RelationalTypeMapping typeMapping); + [return: CA.NotNullIfNotNull("sqlExpression")] + SqlExpression? ApplyTypeMapping([CanBeNull] SqlExpression? sqlExpression, [CanBeNull] RelationalTypeMapping? typeMapping); /// /// Applies default type mapping to given . /// /// A SQL Expression to apply default type mapping. /// A SQL expression with default type mapping applied. - SqlExpression ApplyDefaultTypeMapping([CanBeNull] SqlExpression sqlExpression); + [return: CA.NotNullIfNotNull("sqlExpression")] + SqlExpression? ApplyDefaultTypeMapping([CanBeNull] SqlExpression? sqlExpression); /// /// Creates a new with the given arguments. @@ -63,11 +68,11 @@ public interface ISqlExpressionFactory /// The type of the created expression. /// A type mapping to be assigned to the created expression. /// A with the given arguments. - SqlUnaryExpression MakeUnary( + SqlUnaryExpression? MakeUnary( ExpressionType operatorType, [NotNull] SqlExpression operand, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new with the given arguments. @@ -77,11 +82,11 @@ SqlUnaryExpression MakeUnary( /// The right operand of binary operation. /// A type mapping to be assigned to the created expression. /// A with the given arguments. - SqlBinaryExpression MakeBinary( + SqlBinaryExpression? MakeBinary( ExpressionType operatorType, [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping); + [CanBeNull] RelationalTypeMapping? typeMapping); // Comparison /// @@ -160,7 +165,7 @@ SqlBinaryExpression MakeBinary( SqlBinaryExpression Add( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a which represents a subtraction. @@ -172,7 +177,7 @@ SqlBinaryExpression Add( SqlBinaryExpression Subtract( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a which represents a multiplication. @@ -184,7 +189,7 @@ SqlBinaryExpression Subtract( SqlBinaryExpression Multiply( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a which represents a division. @@ -196,7 +201,7 @@ SqlBinaryExpression Multiply( SqlBinaryExpression Divide( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a which represents a modulo operation. @@ -208,7 +213,7 @@ SqlBinaryExpression Divide( SqlBinaryExpression Modulo( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); // Bitwise /// @@ -221,7 +226,7 @@ SqlBinaryExpression Modulo( SqlBinaryExpression And( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a which represents a bitwise OR operation. @@ -233,7 +238,7 @@ SqlBinaryExpression And( SqlBinaryExpression Or( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); // Other /// @@ -246,7 +251,7 @@ SqlBinaryExpression Or( SqlFunctionExpression Coalesce( [NotNull] SqlExpression left, [NotNull] SqlExpression right, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represent equality to null. @@ -272,7 +277,7 @@ SqlFunctionExpression Coalesce( SqlUnaryExpression Convert( [NotNull] SqlExpression operand, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represent a NOT operation in a SQL tree. @@ -307,7 +312,7 @@ SqlUnaryExpression Convert( CaseExpression Case( [NotNull] SqlExpression operand, [NotNull] IReadOnlyList whenClauses, - [CanBeNull] SqlExpression elseResult); + [CanBeNull] SqlExpression? elseResult); /// /// Creates a new which represent a CASE statement in a SQL tree. @@ -315,7 +320,7 @@ CaseExpression Case( /// A list of to evaluate condition and get result from. /// A value to return if no matches, if any. /// An expression representing a CASE statement in a SQL tree. - CaseExpression Case([NotNull] IReadOnlyList whenClauses, [CanBeNull] SqlExpression elseResult); + CaseExpression Case([NotNull] IReadOnlyList whenClauses, [CanBeNull] SqlExpression? elseResult); /// /// Creates a new which represents a function call in a SQL tree. @@ -330,7 +335,7 @@ SqlFunctionExpression Function( [NotNull] string name, [NotNull] IEnumerable arguments, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -343,11 +348,11 @@ SqlFunctionExpression Function( /// An expression representing a function call in a SQL tree. [Obsolete("Use overload that explicitly specifies value for 'argumentsPropagateNullability' argument.")] SqlFunctionExpression Function( - [CanBeNull] string schema, + [CanBeNull] string? schema, [NotNull] string name, [NotNull] IEnumerable arguments, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -365,7 +370,7 @@ SqlFunctionExpression Function( [NotNull] string name, [NotNull] IEnumerable arguments, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -378,7 +383,7 @@ SqlFunctionExpression Function( SqlFunctionExpression Function( [NotNull] string name, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -393,7 +398,7 @@ SqlFunctionExpression Function( [NotNull] string schema, [NotNull] string name, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -408,7 +413,7 @@ SqlFunctionExpression Function( [NotNull] SqlExpression instance, [NotNull] string name, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -426,7 +431,7 @@ SqlFunctionExpression Function( bool nullable, [NotNull] IEnumerable argumentsPropagateNullability, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -446,7 +451,7 @@ SqlFunctionExpression Function( bool nullable, [NotNull] IEnumerable argumentsPropagateNullability, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a function call in a SQL tree. @@ -468,7 +473,7 @@ SqlFunctionExpression Function( bool instancePropagatesNullability, [NotNull] IEnumerable argumentsPropagateNullability, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a niladic function call in a SQL tree. @@ -482,7 +487,7 @@ SqlFunctionExpression NiladicFunction( [NotNull] string name, bool nullable, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a niladic function call in a SQL tree. @@ -498,7 +503,7 @@ SqlFunctionExpression NiladicFunction( [NotNull] string name, bool nullable, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a niladic function call in a SQL tree. @@ -516,7 +521,7 @@ SqlFunctionExpression NiladicFunction( bool nullable, bool instancePropagatesNullability, [NotNull] Type returnType, - [CanBeNull] RelationalTypeMapping typeMapping = null); + [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents an EXISTS operation in a SQL tree. @@ -551,7 +556,7 @@ SqlFunctionExpression NiladicFunction( /// A pattern to search. /// An optional escape character to use in LIKE. /// An expression representing a LIKE in a SQL tree. - LikeExpression Like([NotNull] SqlExpression match, [NotNull] SqlExpression pattern, [CanBeNull] SqlExpression escapeChar = null); + LikeExpression Like([NotNull] SqlExpression match, [NotNull] SqlExpression pattern, [CanBeNull] SqlExpression? escapeChar = null); /// /// Creates a new which represents a constant in a SQL tree. @@ -559,7 +564,7 @@ SqlFunctionExpression NiladicFunction( /// A value. /// The associated with the expression. /// An expression representing a LIKE in a SQL tree. - SqlConstantExpression Constant([NotNull] object value, [CanBeNull] RelationalTypeMapping typeMapping = null); + SqlConstantExpression Constant([CanBeNull] object? value, [CanBeNull] RelationalTypeMapping? typeMapping = null); /// /// Creates a new which represents a SQL token. @@ -574,7 +579,7 @@ SqlFunctionExpression NiladicFunction( /// /// A to project. /// An expression representing a SELECT in a SQL tree. - SelectExpression Select([CanBeNull] SqlExpression projection); + SelectExpression Select([CanBeNull] SqlExpression? projection); /// /// Creates a new which represents a SELECT in a SQL tree projecting an entity type from diff --git a/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs b/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs index 690e3ee34a8..4dbc054c7ba 100644 --- a/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs +++ b/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs @@ -16,6 +16,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -26,8 +28,9 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal /// public class BufferedDataReader : DbDataReader { - private DbDataReader _underlyingReader; private readonly bool _detailedErrorsEnabled; + + private DbDataReader? _underlyingReader; private List _bufferedDataRecords = new List(); private BufferedDataRecord _currentResultSet; private int _currentResultSetNumber; @@ -45,6 +48,7 @@ public BufferedDataReader([NotNull] DbDataReader reader, bool detailedErrorsEnab { _underlyingReader = reader; _detailedErrorsEnabled = detailedErrorsEnabled; + _currentResultSet = null!; } /// @@ -261,7 +265,7 @@ public static bool IsSupportedValueType([NotNull] Type type) /// public override void Close() { - _bufferedDataRecords = null; + _bufferedDataRecords = null!; _isClosed = true; var reader = _underlyingReader; @@ -612,7 +616,7 @@ public override bool NextResult() return true; } - _currentResultSet = null; + _currentResultSet = null!; return false; } @@ -713,6 +717,38 @@ private sealed class BufferedDataRecord public BufferedDataRecord(bool detailedErrorsEnabled) { _detailedErrorsEnabled = detailedErrorsEnabled; + _dataTypeNames = null!; + _columnNames = null!; + _columns = null!; + _columnTypeCases = null!; + _fieldNameLookup = null!; + _fieldTypes = null!; + _indexMap = null!; + _nullOrdinalToIndexMap = null!; + _ordinalToIndexMap = null!; + _underlyingReader = null!; + + _bools = null!; + _bytes = null!; + _chars = null!; + _dateTimeOffsets = null!; + _dateTimes = null!; + _decimals = null!; + _doubles = null!; + _floats = null!; + _guids = null!; + _ints = null!; + _longs = null!; + _longs = null!; + _nulls = null!; + _objects = null!; + _sbytes = null!; + _shorts = null!; + _tempBools = null!; + _tempNulls = null!; + _uints = null!; + _ulongs = null!; + _ushorts = null!; } public bool IsDataReady { get; private set; } @@ -876,13 +912,13 @@ public BufferedDataRecord Initialize([NotNull] DbDataReader reader, [NotNull] IR } _bools = new BitArray(_tempBools); - _tempBools = null; + _tempBools = null!; _nulls = new BitArray(_tempNulls); - _tempNulls = null; + _tempNulls = null!; _rowCount = _currentRowNumber + 1; _currentRowNumber = -1; - _underlyingReader = null; - _columns = null; + _underlyingReader = null!; + _columns = null!; return this; } @@ -904,13 +940,13 @@ public async Task InitializeAsync( } _bools = new BitArray(_tempBools); - _tempBools = null; + _tempBools = null!; _nulls = new BitArray(_tempNulls); - _tempNulls = null; + _tempNulls = null!; _rowCount = _currentRowNumber + 1; _currentRowNumber = -1; - _underlyingReader = null; - _columns = null; + _underlyingReader = null!; + _columns = null!; return this; } diff --git a/src/EFCore.Relational/Query/Internal/ByteArraySequenceEqualTranslator.cs b/src/EFCore.Relational/Query/Internal/ByteArraySequenceEqualTranslator.cs index 9d354385890..2183749167f 100644 --- a/src/EFCore.Relational/Query/Internal/ByteArraySequenceEqualTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ByteArraySequenceEqualTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -37,8 +39,8 @@ public ByteArraySequenceEqualTranslator([NotNull] ISqlExpressionFactory sqlExpre /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Relational/Query/Internal/CollateTranslator.cs b/src/EFCore.Relational/Query/Internal/CollateTranslator.cs index cb5b958d107..f43a3f6cb44 100644 --- a/src/EFCore.Relational/Query/Internal/CollateTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/CollateTranslator.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -26,8 +28,8 @@ private static readonly MethodInfo _methodInfo /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs index 2cce355400d..8d1ebb65676 100644 --- a/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -72,7 +74,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var innerShaper = Visit(collectionShaperExpression.InnerShaper); var collectionJoin = selectExpression.ApplyCollectionJoin( - projectionBindingExpression.Index.Value, + projectionBindingExpression.Index!.Value, collectionId, innerShaper, collectionShaperExpression.Navigation, @@ -89,7 +91,7 @@ protected override Expression VisitExtension(Expression extensionExpression) nameof(RelationalQueryableExtensions.AsSingleQuery))); } - return collectionJoin; + return collectionJoin!; } return extensionExpression is ShapedQueryExpression shapedQueryExpression diff --git a/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs index ac06c0e49a2..933c9e6ca9d 100644 --- a/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -37,8 +39,8 @@ public ComparisonTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -49,8 +51,8 @@ public virtual SqlExpression Translate( if (method.ReturnType == typeof(int)) { - SqlExpression left = null; - SqlExpression right = null; + SqlExpression? left = null; + SqlExpression? right = null; if (method.Name == nameof(string.Compare) && arguments.Count == 2 && arguments[0].Type == arguments[1].Type) diff --git a/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs index 66a6e6169d4..692cc1cfc1c 100644 --- a/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -38,8 +40,8 @@ public ContainsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -57,6 +59,7 @@ public virtual SqlExpression Translate( if (arguments.Count == 1 && method.IsContainsMethod() + && instance != null && ValidateValues(instance)) { return _sqlExpressionFactory.In(RemoveObjectConvert(arguments[0]), instance, negated: false); diff --git a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs index af6c451b9ed..a382c5f3e56 100644 --- a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -41,8 +43,8 @@ public EnumHasFlagTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactor /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -51,7 +53,8 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (Equals(method, _methodInfo)) + if (Equals(method, _methodInfo) + && instance != null) { var argument = arguments[0]; return instance.Type != argument.Type diff --git a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs index 23cbfc6ce91..0451af9eff6 100644 --- a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -37,8 +39,8 @@ public EqualsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -47,8 +49,8 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - SqlExpression left = null; - SqlExpression right = null; + SqlExpression? left = null; + SqlExpression? right = null; if (method.Name == nameof(object.Equals) && instance != null diff --git a/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs index a0aafb5a51f..71bcc951e79 100644 --- a/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -47,6 +49,8 @@ public FromSqlParameterExpandingExpressionVisitor( _sqlExpressionFactory = dependencies.SqlExpressionFactory; _typeMappingSource = dependencies.TypeMappingSource; _parameterNameGeneratorFactory = dependencies.ParameterNameGeneratorFactory; + _parametersValues = default!; + _parameterNameGenerator = default!; } /// diff --git a/src/EFCore.Relational/Query/Internal/FromSqlQueryRootExpression.cs b/src/EFCore.Relational/Query/Internal/FromSqlQueryRootExpression.cs index 6fb91b1586b..21915c536d5 100644 --- a/src/EFCore.Relational/Query/Internal/FromSqlQueryRootExpression.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlQueryRootExpression.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -118,7 +120,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is FromSqlQueryRootExpression queryRootExpression diff --git a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs index d52963c2028..8b0cf8b193d 100644 --- a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -154,8 +156,8 @@ private sealed class Enumerator : IEnumerator private readonly bool _standAloneStateManager; private readonly bool _detailedErrorsEnabled; - private RelationalDataReader _dataReader; - private int[] _indexMap; + private RelationalDataReader? _dataReader; + private int[]? _indexMap; public Enumerator(FromSqlQueryingEnumerable queryingEnumerable) { @@ -167,12 +169,13 @@ public Enumerator(FromSqlQueryingEnumerable queryingEnumerable) _queryLogger = queryingEnumerable._queryLogger; _standAloneStateManager = queryingEnumerable._standAloneStateManager; _detailedErrorsEnabled = queryingEnumerable._detailedErrorsEnabled; + Current = default!; } public T Current { get; private set; } object IEnumerator.Current - => Current; + => Current!; public bool MoveNext() { @@ -186,11 +189,11 @@ public bool MoveNext() .Execute(true, InitializeReader, null); } - var hasNext = _dataReader.Read(); + var hasNext = _dataReader!.Read(); Current = hasNext - ? _shaper(_relationalQueryContext, _dataReader.DbDataReader, _indexMap) - : default; + ? _shaper(_relationalQueryContext, _dataReader.DbDataReader, _indexMap!) + : default!; return hasNext; } @@ -246,8 +249,8 @@ private sealed class AsyncEnumerator : IAsyncEnumerator private readonly bool _standAloneStateManager; private readonly bool _detailedErrorsEnabled; - private RelationalDataReader _dataReader; - private int[] _indexMap; + private RelationalDataReader? _dataReader; + private int[]? _indexMap; public AsyncEnumerator(FromSqlQueryingEnumerable queryingEnumerable) { @@ -259,6 +262,7 @@ public AsyncEnumerator(FromSqlQueryingEnumerable queryingEnumerable) _queryLogger = queryingEnumerable._queryLogger; _standAloneStateManager = queryingEnumerable._standAloneStateManager; _detailedErrorsEnabled = queryingEnumerable._detailedErrorsEnabled; + Current = default!; } public T Current { get; private set; } @@ -275,11 +279,11 @@ await _relationalQueryContext.ExecutionStrategyFactory.Create() .ExecuteAsync(true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken).ConfigureAwait(false); } - var hasNext = await _dataReader.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false); + var hasNext = await _dataReader!.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false); Current = hasNext - ? _shaper(_relationalQueryContext, _dataReader.DbDataReader, _indexMap) - : default; + ? _shaper(_relationalQueryContext, _dataReader.DbDataReader, _indexMap!) + : default!; return hasNext; } diff --git a/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs index a89ca66c151..1a3cbd64671 100644 --- a/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -38,8 +40,8 @@ public GetValueOrDefaultTranslator([NotNull] ISqlExpressionFactory sqlExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -49,6 +51,7 @@ public virtual SqlExpression Translate( Check.NotNull(logger, nameof(logger)); if (method.Name == nameof(Nullable.GetValueOrDefault) + && instance != null && method.ReturnType.IsNumeric()) { return _sqlExpressionFactory.Coalesce( diff --git a/src/EFCore.Relational/Query/Internal/IRelationalQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/IRelationalQueryingEnumerable.cs index 294c631109c..855011a6566 100644 --- a/src/EFCore.Relational/Query/Internal/IRelationalQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/IRelationalQueryingEnumerable.cs @@ -3,6 +3,8 @@ using System.Data.Common; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs index 9eae550a94d..b305e31480a 100644 --- a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -47,8 +49,8 @@ public LikeTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs b/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs index fbd4176fd09..aed293011ec 100644 --- a/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -37,8 +39,8 @@ public NullableMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFac /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -47,7 +49,8 @@ public virtual SqlExpression Translate( Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); - if (member.DeclaringType.IsNullableValueType()) + if (member.DeclaringType.IsNullableValueType() + && instance != null) { switch (member.Name) { diff --git a/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs b/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs index 1e579627f79..6411cd37e0d 100644 --- a/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs index 0a8e9a23692..ae1fbb89cef 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Caching.Memory; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -39,7 +41,7 @@ public RelationalCommandCache( [NotNull] IQuerySqlGeneratorFactory querySqlGeneratorFactory, [NotNull] IRelationalParameterBasedSqlProcessorFactory relationalParameterBasedSqlProcessorFactory, [NotNull] SelectExpression selectExpression, - [NotNull] IReadOnlyList readerColumns, + [CanBeNull] IReadOnlyList? readerColumns, bool useRelationalNulls) { _memoryCache = memoryCache; @@ -55,7 +57,7 @@ public RelationalCommandCache( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IReadOnlyList ReaderColumns { get; } + public virtual IReadOnlyList? ReaderColumns { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -129,7 +131,7 @@ public CommandCacheKey(SelectExpression selectExpression, IReadOnlyDictionary obj is CommandCacheKey commandCacheKey && Equals(commandCacheKey); diff --git a/src/EFCore.Relational/Query/Internal/RelationalParameterBasedSqlProcessorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalParameterBasedSqlProcessorFactory.cs index e0568526184..adeff040d9a 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalParameterBasedSqlProcessorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalParameterBasedSqlProcessorFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs index e15ceee0707..416b1f9b130 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs @@ -14,6 +14,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -54,6 +56,8 @@ public RelationalProjectionBindingExpressionVisitor( _queryableMethodTranslatingExpressionVisitor = queryableMethodTranslatingExpressionVisitor; _sqlTranslator = sqlTranslatingExpressionVisitor; _includeFindingExpressionVisitor = new IncludeFindingExpressionVisitor(); + _selectExpression = null!; + _existingProjections = Array.Empty(); } /// @@ -85,11 +89,11 @@ public virtual Expression Translate([NotNull] SelectExpression selectExpression, } _selectExpression.ReplaceProjectionMapping(_projectionMapping); - _selectExpression = null; + _selectExpression = null!; _projectionMembers.Clear(); _projectionMapping.Clear(); - result = MatchTypes(result, expression.Type); + result = MatchTypes(result!, expression.Type); return result; } @@ -100,7 +104,7 @@ public virtual Expression Translate([NotNull] SelectExpression selectExpression, /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override Expression Visit(Expression expression) + public override Expression? Visit(Expression? expression) { if (expression == null) { @@ -162,9 +166,9 @@ public override Expression Visit(Expression expression) case MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression: return _selectExpression.AddCollectionProjection( _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( - materializeCollectionNavigationExpression.Subquery), + materializeCollectionNavigationExpression.Subquery)!, materializeCollectionNavigationExpression.Navigation, - materializeCollectionNavigationExpression.Navigation.ClrType.TryGetSequenceType()); + materializeCollectionNavigationExpression.Navigation.ClrType.TryGetSequenceType()!); case MethodCallExpression methodCallExpression: { @@ -256,8 +260,8 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) /// protected override Expression VisitBinary(BinaryExpression binaryExpression) { - var left = MatchTypes(Visit(binaryExpression.Left), binaryExpression.Left.Type); - var right = MatchTypes(Visit(binaryExpression.Right), binaryExpression.Right.Type); + var left = MatchTypes(Visit(binaryExpression.Left)!, binaryExpression.Left.Type); + var right = MatchTypes(Visit(binaryExpression.Right)!, binaryExpression.Right.Type); return binaryExpression.Update(left, VisitAndConvert(binaryExpression.Conversion, "VisitBinary"), right); } @@ -270,9 +274,9 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) /// protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { - var test = Visit(conditionalExpression.Test); - var ifTrue = Visit(conditionalExpression.IfTrue); - var ifFalse = Visit(conditionalExpression.IfFalse); + var test = Visit(conditionalExpression.Test)!; + var ifTrue = Visit(conditionalExpression.IfTrue)!; + var ifFalse = Visit(conditionalExpression.IfFalse)!; if (test.Type == typeof(bool?)) { @@ -288,7 +292,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitExtension(Expression extensionExpression) + protected override Expression? VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); @@ -307,7 +311,7 @@ protected override Expression VisitExtension(Expression extensionExpression) if (_clientEval) { var indexMap = new Dictionary(); - foreach (var item in projectionBindingExpression.IndexMap) + foreach (var item in projectionBindingExpression.IndexMap!) { indexMap[item.Key] = _selectExpression.AddToProjection(_existingProjections[item.Value]); } @@ -357,7 +361,7 @@ protected override Expression VisitExtension(Expression extensionExpression) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override ElementInit VisitElementInit(ElementInit elementInit) - => elementInit.Update(elementInit.Arguments.Select(e => MatchTypes(Visit(e), e.Type))); + => elementInit.Update(elementInit.Arguments.Select(e => MatchTypes(Visit(e)!, e.Type))); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -395,10 +399,10 @@ protected override Expression VisitMember(MemberExpression memberExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override MemberAssignment VisitMemberAssignment(MemberAssignment memberAssignment) + protected override MemberAssignment? VisitMemberAssignment(MemberAssignment memberAssignment) { var expression = memberAssignment.Expression; - Expression visitedExpression; + Expression? visitedExpression; if (_clientEval) { visitedExpression = Visit(memberAssignment.Expression); @@ -417,7 +421,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment membe _projectionMembers.Pop(); } - visitedExpression = MatchTypes(visitedExpression, expression.Type); + visitedExpression = MatchTypes(visitedExpression!, expression.Type); return memberAssignment.Update(visitedExpression); } @@ -428,7 +432,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment membe /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) + protected override Expression? VisitMemberInit(MemberInitExpression memberInitExpression) { Check.NotNull(memberInitExpression, nameof(memberInitExpression)); @@ -470,7 +474,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp for (var i = 0; i < methodCallExpression.Arguments.Count; i++) { var argument = methodCallExpression.Arguments[i]; - arguments[i] = MatchTypes(Visit(argument), argument.Type); + arguments[i] = MatchTypes(Visit(argument)!, argument.Type); } Expression updatedMethodCallExpression = methodCallExpression.Update( @@ -501,7 +505,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitNew(NewExpression newExpression) + protected override Expression? VisitNew(NewExpression newExpression) { Check.NotNull(newExpression, nameof(newExpression)); @@ -520,7 +524,7 @@ protected override Expression VisitNew(NewExpression newExpression) for (var i = 0; i < newArguments.Length; i++) { var argument = newExpression.Arguments[i]; - Expression visitedArgument; + Expression? visitedArgument; if (_clientEval) { visitedArgument = Visit(argument); @@ -538,7 +542,7 @@ protected override Expression VisitNew(NewExpression newExpression) _projectionMembers.Pop(); } - newArguments[i] = MatchTypes(visitedArgument, argument.Type); + newArguments[i] = MatchTypes(visitedArgument!, argument.Type); } return newExpression.Update(newArguments); @@ -551,7 +555,7 @@ protected override Expression VisitNew(NewExpression newExpression) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) - => newArrayExpression.Update(newArrayExpression.Expressions.Select(e => MatchTypes(Visit(e), e.Type))); + => newArrayExpression.Update(newArrayExpression.Expressions.Select(e => MatchTypes(Visit(e)!, e.Type))); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -561,7 +565,7 @@ protected override Expression VisitNewArray(NewArrayExpression newArrayExpressio /// protected override Expression VisitUnary(UnaryExpression unaryExpression) { - var operand = Visit(unaryExpression.Operand); + var operand = Visit(unaryExpression.Operand)!; return (unaryExpression.NodeType == ExpressionType.Convert || unaryExpression.NodeType == ExpressionType.ConvertChecked) diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryCompilationContextFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryCompilationContextFactory.cs index 58803ae45ee..ea0f6299e84 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryCompilationContextFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryCompilationContextFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryContextFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryContextFactory.cs index a12db9f8a9c..dfcadfa66bd 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryContextFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryContextFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryMetadataExtractingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryMetadataExtractingExpressionVisitor.cs index 474d5fb1565..52a21dd9872 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryMetadataExtractingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryMetadataExtractingExpressionVisitor.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryStringFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryStringFactory.cs index 9a8385c72ce..2661d889340 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryStringFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryStringFactory.cs @@ -5,6 +5,8 @@ using System.Text; using Microsoft.EntityFrameworkCore.Storage.Internal; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs index 4b40cf6ec4b..2bfbb6e95f1 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPostprocessorFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs index 3b5e1598e39..afc3911f30b 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryTranslationPreprocessorFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs index 113add1e61f..bff41f31d18 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs index 35e030aeeec..5da1501d8d9 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryCompilingExpressionVisitorFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs index a2626c17717..495fd9dfe00 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs index ad33ad59c90..b2848ef93a1 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -152,7 +154,7 @@ private Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression) private SqlExpression TryCompensateForBoolWithValueConverter(SqlExpression sqlExpression) { if (sqlExpression is ColumnExpression columnExpression - && columnExpression.TypeMapping.ClrType == typeof(bool) + && columnExpression.TypeMapping!.ClrType == typeof(bool) && columnExpression.TypeMapping.Converter != null) { return _sqlExpressionFactory.Equal( diff --git a/src/EFCore.Relational/Query/Internal/ResultContext.cs b/src/EFCore.Relational/Query/Internal/ResultContext.cs index 95614f75ef9..5cb9f7c7e6a 100644 --- a/src/EFCore.Relational/Query/Internal/ResultContext.cs +++ b/src/EFCore.Relational/Query/Internal/ResultContext.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -19,6 +21,6 @@ public class ResultContext /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual object[] Values { get; [param: NotNull] set; } + public virtual object[]? Values { get; [param: CanBeNull] set; } } } diff --git a/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs index e80aa3f2f29..82e1d5076f1 100644 --- a/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/SelectExpressionPruningExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SelectExpressionPruningExpressionVisitor.cs index a7675c60d70..0ac48718fb4 100644 --- a/src/EFCore.Relational/Query/Internal/SelectExpressionPruningExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SelectExpressionPruningExpressionVisitor.cs @@ -3,6 +3,9 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -20,7 +23,8 @@ public class SelectExpressionPruningExpressionVisitor : ExpressionVisitor /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { switch (expression) { diff --git a/src/EFCore.Relational/Query/Internal/SingleQueryCollectionContext.cs b/src/EFCore.Relational/Query/Internal/SingleQueryCollectionContext.cs index bd764db8394..51251a0a91a 100644 --- a/src/EFCore.Relational/Query/Internal/SingleQueryCollectionContext.cs +++ b/src/EFCore.Relational/Query/Internal/SingleQueryCollectionContext.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -20,8 +22,8 @@ public class SingleQueryCollectionContext /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SingleQueryCollectionContext( - [CanBeNull] object parent, - [NotNull] object collection, + [CanBeNull] object? parent, + [CanBeNull] object? collection, [NotNull] object[] parentIdentifier, [NotNull] object[] outerIdentifier) { @@ -30,6 +32,7 @@ public SingleQueryCollectionContext( ParentIdentifier = parentIdentifier; OuterIdentifier = outerIdentifier; ResultContext = new ResultContext(); + SelfIdentifier = null!; } /// @@ -46,7 +49,7 @@ public SingleQueryCollectionContext( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual object Parent { get; } + public virtual object? Parent { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -54,7 +57,7 @@ public SingleQueryCollectionContext( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual object Collection { get; } + public virtual object? Collection { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -78,7 +81,7 @@ public SingleQueryCollectionContext( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual object[] SelfIdentifier { get; private set; } + public virtual object[]? SelfIdentifier { get; private set; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -86,7 +89,7 @@ public SingleQueryCollectionContext( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void UpdateSelfIdentifier([NotNull] object[] selfIdentifier) + public virtual void UpdateSelfIdentifier([CanBeNull] object[]? selfIdentifier) { SelfIdentifier = selfIdentifier; } diff --git a/src/EFCore.Relational/Query/Internal/SingleQueryResultCoordinator.cs b/src/EFCore.Relational/Query/Internal/SingleQueryResultCoordinator.cs index f23908c949a..2eb92be3f71 100644 --- a/src/EFCore.Relational/Query/Internal/SingleQueryResultCoordinator.cs +++ b/src/EFCore.Relational/Query/Internal/SingleQueryResultCoordinator.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -55,7 +57,7 @@ public SingleQueryResultCoordinator() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IList Collections { get; } = new List(); + public virtual IList Collections { get; } = new List(); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs index 570382f50eb..a5422ee1ad6 100644 --- a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -122,8 +124,8 @@ private sealed class Enumerator : IEnumerator private readonly bool _standAloneStateManager; private readonly bool _detailedErrorsEnabled; - private RelationalDataReader _dataReader; - private SingleQueryResultCoordinator _resultCoordinator; + private RelationalDataReader? _dataReader; + private SingleQueryResultCoordinator? _resultCoordinator; public Enumerator(SingleQueryingEnumerable queryingEnumerable) { @@ -134,12 +136,13 @@ public Enumerator(SingleQueryingEnumerable queryingEnumerable) _queryLogger = queryingEnumerable._queryLogger; _standAloneStateManager = queryingEnumerable._standAloneStateManager; _detailedErrorsEnabled = queryingEnumerable._detailedErrorsEnabled; + Current = default!; } public T Current { get; private set; } object IEnumerator.Current - => Current; + => Current!; public bool MoveNext() { @@ -153,8 +156,8 @@ public bool MoveNext() .Execute(true, InitializeReader, null); } - var hasNext = _resultCoordinator.HasNext ?? _dataReader.Read(); - Current = default; + var hasNext = _resultCoordinator!.HasNext ?? _dataReader!.Read(); + Current = default!; if (hasNext) { @@ -163,7 +166,7 @@ public bool MoveNext() _resultCoordinator.ResultReady = true; _resultCoordinator.HasNext = null; Current = _shaper( - _relationalQueryContext, _dataReader.DbDataReader, _resultCoordinator.ResultContext, + _relationalQueryContext, _dataReader!.DbDataReader, _resultCoordinator.ResultContext, _resultCoordinator); if (_resultCoordinator.ResultReady) { @@ -239,8 +242,8 @@ private sealed class AsyncEnumerator : IAsyncEnumerator private readonly bool _standAloneStateManager; private readonly bool _detailedErrorsEnabled; - private RelationalDataReader _dataReader; - private SingleQueryResultCoordinator _resultCoordinator; + private RelationalDataReader? _dataReader; + private SingleQueryResultCoordinator? _resultCoordinator; public AsyncEnumerator(SingleQueryingEnumerable queryingEnumerable) { @@ -251,6 +254,7 @@ public AsyncEnumerator(SingleQueryingEnumerable queryingEnumerable) _queryLogger = queryingEnumerable._queryLogger; _standAloneStateManager = queryingEnumerable._standAloneStateManager; _detailedErrorsEnabled = queryingEnumerable._detailedErrorsEnabled; + Current = default!; } public T Current { get; private set; } @@ -268,9 +272,9 @@ await _relationalQueryContext.ExecutionStrategyFactory.Create() .ConfigureAwait(false); } - var hasNext = _resultCoordinator.HasNext - ?? await _dataReader.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false); - Current = default; + var hasNext = _resultCoordinator!.HasNext + ?? await _dataReader!.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false); + Current = default!; if (hasNext) { @@ -279,7 +283,7 @@ await _relationalQueryContext.ExecutionStrategyFactory.Create() _resultCoordinator.ResultReady = true; _resultCoordinator.HasNext = null; Current = _shaper( - _relationalQueryContext, _dataReader.DbDataReader, _resultCoordinator.ResultContext, + _relationalQueryContext, _dataReader!.DbDataReader, _resultCoordinator.ResultContext, _resultCoordinator); if (_resultCoordinator.ResultReady) { diff --git a/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs index d0775af8709..d51ac64462e 100644 --- a/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs @@ -6,6 +6,8 @@ using System.Linq; using System.Linq.Expressions; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -76,7 +78,7 @@ private LambdaExpression RewriteCollectionInclude( { var selectorParameter = selector.Parameters[0]; var selectorBody = selector.Body; - var sourceElementType = source.Type.TryGetSequenceType(); + var sourceElementType = source.Type.TryGetSequenceType()!; if (reverseOrdering) { diff --git a/src/EFCore.Relational/Query/Internal/SplitQueryCollectionContext.cs b/src/EFCore.Relational/Query/Internal/SplitQueryCollectionContext.cs index 4a20f14237b..6ef8f622f84 100644 --- a/src/EFCore.Relational/Query/Internal/SplitQueryCollectionContext.cs +++ b/src/EFCore.Relational/Query/Internal/SplitQueryCollectionContext.cs @@ -3,6 +3,8 @@ using JetBrains.Annotations; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -20,8 +22,8 @@ public class SplitQueryCollectionContext /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SplitQueryCollectionContext( - [CanBeNull] object parent, - [NotNull] object collection, + [CanBeNull] object? parent, + [CanBeNull] object? collection, [NotNull] object[] parentIdentifier) { Parent = parent; @@ -44,7 +46,7 @@ public SplitQueryCollectionContext( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual object Parent { get; } + public virtual object? Parent { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -52,7 +54,7 @@ public SplitQueryCollectionContext( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual object Collection { get; } + public virtual object? Collection { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Query/Internal/SplitQueryDataReaderContext.cs b/src/EFCore.Relational/Query/Internal/SplitQueryDataReaderContext.cs index 16d38476f8a..64e0129981d 100644 --- a/src/EFCore.Relational/Query/Internal/SplitQueryDataReaderContext.cs +++ b/src/EFCore.Relational/Query/Internal/SplitQueryDataReaderContext.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/Internal/SplitQueryResultCoordinator.cs b/src/EFCore.Relational/Query/Internal/SplitQueryResultCoordinator.cs index ecf50d062ed..900f8aec4b2 100644 --- a/src/EFCore.Relational/Query/Internal/SplitQueryResultCoordinator.cs +++ b/src/EFCore.Relational/Query/Internal/SplitQueryResultCoordinator.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -40,7 +42,7 @@ public SplitQueryResultCoordinator() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IList Collections { get; } = new List(); + public virtual IList Collections { get; } = new List(); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -48,7 +50,7 @@ public SplitQueryResultCoordinator() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IList DataReaders { get; } = new List(); + public virtual IList DataReaders { get; } = new List(); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs index e1763674f72..a9e0c25a83c 100644 --- a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -130,9 +132,9 @@ private sealed class Enumerator : IEnumerator private readonly bool _standAloneStateManager; private readonly bool _detailedErrorsEnabled; - private RelationalDataReader _dataReader; - private SplitQueryResultCoordinator _resultCoordinator; - private IExecutionStrategy _executionStrategy; + private RelationalDataReader? _dataReader; + private SplitQueryResultCoordinator? _resultCoordinator; + private IExecutionStrategy? _executionStrategy; public Enumerator(SplitQueryingEnumerable queryingEnumerable) { @@ -144,12 +146,13 @@ public Enumerator(SplitQueryingEnumerable queryingEnumerable) _queryLogger = queryingEnumerable._queryLogger; _standAloneStateManager = queryingEnumerable._standAloneStateManager; _detailedErrorsEnabled = queryingEnumerable._detailedErrorsEnabled; + Current = default!; } public T Current { get; private set; } object IEnumerator.Current - => Current; + => Current!; public bool MoveNext() { @@ -167,15 +170,15 @@ public bool MoveNext() _executionStrategy.Execute(true, InitializeReader, null); } - var hasNext = _dataReader.Read(); - Current = default; + var hasNext = _dataReader!.Read(); + Current = default!; if (hasNext) { - _resultCoordinator.ResultContext.Values = null; + _resultCoordinator!.ResultContext.Values = null; _shaper( _relationalQueryContext, _dataReader.DbDataReader, _resultCoordinator.ResultContext, _resultCoordinator); - _relatedDataLoaders?.Invoke(_relationalQueryContext, _executionStrategy, _resultCoordinator); + _relatedDataLoaders?.Invoke(_relationalQueryContext, _executionStrategy!, _resultCoordinator); Current = _shaper( _relationalQueryContext, _dataReader.DbDataReader, _resultCoordinator.ResultContext, _resultCoordinator); } @@ -216,12 +219,17 @@ private bool InitializeReader(DbContext _, bool result) public void Dispose() { _dataReader?.Dispose(); - foreach (var dataReader in _resultCoordinator.DataReaders) + if (_resultCoordinator != null) { - dataReader?.DataReader.Dispose(); - } + foreach (var dataReader in _resultCoordinator.DataReaders) + { + dataReader?.DataReader.Dispose(); + } + + _resultCoordinator.DataReaders.Clear(); - _resultCoordinator.DataReaders.Clear(); + _resultCoordinator = null; + } _dataReader = null; } @@ -241,9 +249,9 @@ private sealed class AsyncEnumerator : IAsyncEnumerator private readonly bool _standAloneStateManager; private readonly bool _detailedErrorEnabled; - private RelationalDataReader _dataReader; - private SplitQueryResultCoordinator _resultCoordinator; - private IExecutionStrategy _executionStrategy; + private RelationalDataReader? _dataReader; + private SplitQueryResultCoordinator? _resultCoordinator; + private IExecutionStrategy? _executionStrategy; public AsyncEnumerator(SplitQueryingEnumerable queryingEnumerable) { @@ -255,6 +263,7 @@ public AsyncEnumerator(SplitQueryingEnumerable queryingEnumerable) _queryLogger = queryingEnumerable._queryLogger; _standAloneStateManager = queryingEnumerable._standAloneStateManager; _detailedErrorEnabled = queryingEnumerable._detailedErrorsEnabled; + Current = default!; } public T Current { get; private set; } @@ -276,17 +285,17 @@ await _executionStrategy.ExecuteAsync( true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken).ConfigureAwait(false); } - var hasNext = await _dataReader.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false); - Current = default; + var hasNext = await _dataReader!.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false); + Current = default!; if (hasNext) { - _resultCoordinator.ResultContext.Values = null; + _resultCoordinator!.ResultContext.Values = null; _shaper( _relationalQueryContext, _dataReader.DbDataReader, _resultCoordinator.ResultContext, _resultCoordinator); if (_relatedDataLoaders != null) { - await _relatedDataLoaders(_relationalQueryContext, _executionStrategy, _resultCoordinator) + await _relatedDataLoaders(_relationalQueryContext, _executionStrategy!, _resultCoordinator) .ConfigureAwait(false); } @@ -334,16 +343,19 @@ public async ValueTask DisposeAsync() if (_dataReader != null) { await _dataReader.DisposeAsync().ConfigureAwait(false); - foreach (var dataReader in _resultCoordinator.DataReaders) + if (_resultCoordinator != null) { - if (dataReader != null) + foreach (var dataReader in _resultCoordinator.DataReaders) { - await dataReader.DataReader.DisposeAsync().ConfigureAwait(false); + if (dataReader != null) + { + await dataReader.DataReader.DisposeAsync().ConfigureAwait(false); + } } - } - - _resultCoordinator.DataReaders.Clear(); + _resultCoordinator.DataReaders.Clear(); + _resultCoordinator = null; + } _dataReader = null; } } diff --git a/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs index c4575af10cb..a759673ff8d 100644 --- a/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -138,7 +140,7 @@ private Expression VisitSqlUnary([NotNull] SqlUnaryExpression sqlUnaryExpression sqlUnaryExpression.OperatorType, newOperand, sqlUnaryExpression.Type, - sqlUnaryExpression.TypeMapping); + sqlUnaryExpression.TypeMapping!); } private SqlExpression SimplifyUnaryExpression( @@ -198,7 +200,7 @@ private SqlExpression SimplifyUnaryExpression( : ExpressionType.AndAlso, newLeft, newRight, - binaryOperand.TypeMapping); + binaryOperand.TypeMapping!); } // those optimizations are only valid in 2-value logic @@ -211,7 +213,7 @@ private SqlExpression SimplifyUnaryExpression( negated, binaryOperand.Left, binaryOperand.Right, - binaryOperand.TypeMapping); + binaryOperand.TypeMapping!); } } break; @@ -229,7 +231,7 @@ private SqlExpression SimplifyUnaryExpression( typeMapping); } - return _sqlExpressionFactory.MakeUnary(operatorType, operand, type, typeMapping); + return _sqlExpressionFactory.MakeUnary(operatorType, operand, type, typeMapping)!; } private SqlExpression SimplifyNullNotNullExpression( @@ -304,6 +306,7 @@ private SqlExpression SimplifyNullNotNullExpression( case SqlFunctionExpression sqlFunctionExpression when sqlFunctionExpression.IsBuiltIn + && sqlFunctionExpression.Arguments != null && string.Equals("COALESCE", sqlFunctionExpression.Name, StringComparison.OrdinalIgnoreCase): // for coalesce: // (a ?? b) == null -> a == null && b == null @@ -325,7 +328,7 @@ when sqlFunctionExpression.IsBuiltIn break; } - return _sqlExpressionFactory.MakeUnary(operatorType, operand, type, typeMapping); + return _sqlExpressionFactory.MakeUnary(operatorType, operand, type, typeMapping)!; } private Expression VisitSqlBinary([NotNull] SqlBinaryExpression sqlBinaryExpression) @@ -337,7 +340,7 @@ private Expression VisitSqlBinary([NotNull] SqlBinaryExpression sqlBinaryExpress sqlBinaryExpression.OperatorType, newLeft, newRight, - sqlBinaryExpression.TypeMapping); + sqlBinaryExpression.TypeMapping!); } private SqlExpression SimplifyBinaryExpression( @@ -418,7 +421,7 @@ private SqlExpression SimplifyBinaryExpression( break; } - return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping); + return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping)!; } private SqlExpression SimplifyNullComparisonExpression( @@ -448,15 +451,15 @@ private SqlExpression SimplifyNullComparisonExpression( } } - return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping); + return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping)!; } private SqlExpression SimplifyBoolConstantComparisonExpression( ExpressionType operatorType, SqlExpression left, SqlExpression right, - SqlConstantExpression leftBoolConstant, - SqlConstantExpression rightBoolConstant, + SqlConstantExpression? leftBoolConstant, + SqlConstantExpression? rightBoolConstant, RelationalTypeMapping typeMapping) { if (leftBoolConstant != null && rightBoolConstant != null) @@ -500,7 +503,7 @@ private SqlExpression SimplifyBoolConstantComparisonExpression( : right; } - return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping); + return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping)!; static bool CanOptimize(SqlExpression operand) => operand is LikeExpression @@ -547,7 +550,7 @@ private SqlExpression SimplifyLogicalSqlBinaryExpression( : left; } - return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping); + return _sqlExpressionFactory.MakeBinary(operatorType, left, right, typeMapping)!; } } } diff --git a/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs index e7f06449104..a2b71fb6f22 100644 --- a/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs @@ -9,6 +9,9 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -68,7 +71,7 @@ protected override Expression VisitExtension(Expression extensionExpression) return base.VisitExtension(extensionExpression); } - private bool IsCompareTo(CaseExpression caseExpression) + private bool IsCompareTo([CA.NotNullWhen(true)] CaseExpression? caseExpression) { if (caseExpression != null && caseExpression.Operand == null @@ -233,10 +236,8 @@ private Expression SimplifySqlBinary(SqlBinaryExpression sqlBinaryExpression) if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso || sqlBinaryExpression.OperatorType == ExpressionType.OrElse) { - var leftCandidateInfo = GetInExressionCandidateInfo(left); - var rightCandidateInfo = GetInExressionCandidateInfo(right); - if (leftCandidateInfo.OptimizeCandidate - && rightCandidateInfo.OptimizeCandidate + if (TryGetInExressionCandidateInfo(left, out var leftCandidateInfo) + && TryGetInExressionCandidateInfo(right, out var rightCandidateInfo) && leftCandidateInfo.ColumnExpression == rightCandidateInfo.ColumnExpression && leftCandidateInfo.OperationType == rightCandidateInfo.OperationType) { @@ -374,29 +375,32 @@ private List BuildListFromEnumerable(IEnumerable collection) return result; } - private (bool OptimizeCandidate, ColumnExpression ColumnExpression, object ConstantValue, RelationalTypeMapping TypeMapping, - ExpressionType OperationType) GetInExressionCandidateInfo(SqlExpression sqlExpression) + private bool TryGetInExressionCandidateInfo( + SqlExpression sqlExpression, + [CA.MaybeNullWhen(false)] out (ColumnExpression ColumnExpression, object ConstantValue, RelationalTypeMapping TypeMapping, ExpressionType OperationType) candidateInfo) { if (sqlExpression is SqlUnaryExpression sqlUnaryExpression && sqlUnaryExpression.OperatorType == ExpressionType.Not) { - var result = GetInExressionCandidateInfo(sqlUnaryExpression.Operand); - if (result.OptimizeCandidate) + if (TryGetInExressionCandidateInfo(sqlUnaryExpression.Operand, out var inner)) { - return (result.OptimizeCandidate, result.ColumnExpression, result.ConstantValue, result.TypeMapping, - result.OperationType == ExpressionType.Equal ? ExpressionType.NotEqual : ExpressionType.Equal); + candidateInfo = (inner.ColumnExpression, inner.ConstantValue, inner.TypeMapping, + inner.OperationType == ExpressionType.Equal ? ExpressionType.NotEqual : ExpressionType.Equal); + + return true; } } else if (sqlExpression is SqlBinaryExpression sqlBinaryExpression && (sqlBinaryExpression.OperatorType == ExpressionType.Equal || sqlBinaryExpression.OperatorType == ExpressionType.NotEqual)) { - var column = sqlBinaryExpression.Left as ColumnExpression ?? sqlBinaryExpression.Right as ColumnExpression; - var constant = sqlBinaryExpression.Left as SqlConstantExpression ?? sqlBinaryExpression.Right as SqlConstantExpression; + var column = (sqlBinaryExpression.Left as ColumnExpression ?? sqlBinaryExpression.Right as ColumnExpression)!; + var constant = (sqlBinaryExpression.Left as SqlConstantExpression ?? sqlBinaryExpression.Right as SqlConstantExpression)!; if (column != null && constant != null) { - return (true, column, constant.Value, constant.TypeMapping, sqlBinaryExpression.OperatorType); + candidateInfo = (column, constant.Value, constant.TypeMapping!, sqlBinaryExpression.OperatorType); + return true; } } else if (sqlExpression is InExpression inExpression @@ -404,11 +408,14 @@ private List BuildListFromEnumerable(IEnumerable collection) && inExpression.Subquery == null && inExpression.Values is SqlConstantExpression valuesConstant) { - return (true, column, valuesConstant.Value, valuesConstant.TypeMapping, + candidateInfo = (column, valuesConstant.Value, valuesConstant.TypeMapping!, inExpression.IsNegated ? ExpressionType.NotEqual : ExpressionType.Equal); + + return true; } - return (false, default, default, default, default); + candidateInfo = default; + return false; } } } diff --git a/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs b/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs index e2b77948e74..bc92d47d664 100644 --- a/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -43,8 +45,8 @@ public StringMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFacto /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs index 93dc016a986..7a7240e3c0d 100644 --- a/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs @@ -6,6 +6,9 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query.Internal { @@ -23,7 +26,8 @@ public class TableAliasUniquifyingExpressionVisitor : ExpressionVisitor /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { switch (expression) { diff --git a/src/EFCore.Relational/Query/Internal/TableValuedFunctionQueryRootExpression.cs b/src/EFCore.Relational/Query/Internal/TableValuedFunctionQueryRootExpression.cs index f5dc38a7437..7ca31589ab3 100644 --- a/src/EFCore.Relational/Query/Internal/TableValuedFunctionQueryRootExpression.cs +++ b/src/EFCore.Relational/Query/Internal/TableValuedFunctionQueryRootExpression.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// @@ -99,7 +101,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is TableValuedFunctionQueryRootExpression queryRootExpression diff --git a/src/EFCore.Relational/Query/Internal/TableValuedFunctionToQueryRootConvertingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/TableValuedFunctionToQueryRootConvertingExpressionVisitor.cs index 5eb954193ce..ed098c8051a 100644 --- a/src/EFCore.Relational/Query/Internal/TableValuedFunctionToQueryRootConvertingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/TableValuedFunctionToQueryRootConvertingExpressionVisitor.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.Internal { /// diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index 8018d64af5e..6f8a7f60249 100644 --- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -60,6 +62,7 @@ public QuerySqlGenerator([NotNull] QuerySqlGeneratorDependencies dependencies) _relationalCommandBuilderFactory = dependencies.RelationalCommandBuilderFactory; _sqlGenerationHelper = dependencies.SqlGenerationHelper; + _relationalCommandBuilder = default!; } /// @@ -163,7 +166,7 @@ protected override Expression VisitSelect(SelectExpression selectExpression) return selectExpression; } - IDisposable subQueryIndent = null; + IDisposable? subQueryIndent = null; if (selectExpression.Alias != null) { @@ -226,7 +229,7 @@ protected override Expression VisitSelect(SelectExpression selectExpression) if (selectExpression.Alias != null) { - subQueryIndent.Dispose(); + subQueryIndent!.Dispose(); _relationalCommandBuilder.AppendLine() .Append(")" + AliasSeparator + _sqlGenerationHelper.DelimitIdentifier(selectExpression.Alias)); @@ -289,7 +292,7 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction if (!sqlFunctionExpression.IsNiladic) { _relationalCommandBuilder.Append("("); - GenerateList(sqlFunctionExpression.Arguments, e => Visit(e)); + GenerateList(sqlFunctionExpression.Arguments!, e => Visit(e)); _relationalCommandBuilder.Append(")"); } @@ -351,7 +354,7 @@ protected override Expression VisitTable(TableExpression tableExpression) private void GenerateFromSql(FromSqlExpression fromSqlExpression) { var sql = fromSqlExpression.Sql; - string[] substitutions = null; + string[]? substitutions = null; switch (fromSqlExpression.Arguments) { @@ -384,7 +387,7 @@ private void GenerateFromSql(FromSqlExpression fromSqlExpression) } else if (value is SqlConstantExpression sqlConstantExpression) { - substitutions[i] = sqlConstantExpression.TypeMapping.GenerateSqlLiteral(sqlConstantExpression.Value); + substitutions[i] = sqlConstantExpression.TypeMapping!.GenerateSqlLiteral(sqlConstantExpression.Value); } } @@ -551,7 +554,7 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant Check.NotNull(sqlConstantExpression, nameof(sqlConstantExpression)); _relationalCommandBuilder - .Append(sqlConstantExpression.TypeMapping.GenerateSqlLiteral(sqlConstantExpression.Value)); + .Append(sqlConstantExpression.TypeMapping!.GenerateSqlLiteral(sqlConstantExpression.Value)); return sqlConstantExpression; } @@ -710,7 +713,7 @@ protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpressio } _relationalCommandBuilder.Append(" AS "); - _relationalCommandBuilder.Append(sqlUnaryExpression.TypeMapping.StoreType); + _relationalCommandBuilder.Append(sqlUnaryExpression.TypeMapping!.StoreType); _relationalCommandBuilder.Append(")"); break; } @@ -924,7 +927,7 @@ protected virtual void GenerateLimitOffset([NotNull] SelectExpression selectExpr private void GenerateList( IReadOnlyList items, Action generationAction, - Action joinAction = null) + Action? joinAction = null) { joinAction ??= (isb => isb.Append(", ")); diff --git a/src/EFCore.Relational/Query/QuerySqlGeneratorDependencies.cs b/src/EFCore.Relational/Query/QuerySqlGeneratorDependencies.cs index 5a6d78f67ca..f9a5a4ca9e9 100644 --- a/src/EFCore.Relational/Query/QuerySqlGeneratorDependencies.cs +++ b/src/EFCore.Relational/Query/QuerySqlGeneratorDependencies.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs index 1b36d90cb37..4b349e0037a 100644 --- a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -66,11 +68,11 @@ public RelationalCollectionShaperExpression( [NotNull] Expression parentIdentifier, [NotNull] Expression outerIdentifier, [NotNull] Expression selfIdentifier, - [CanBeNull] IReadOnlyList parentIdentifierValueComparers, - [CanBeNull] IReadOnlyList outerIdentifierValueComparers, - [CanBeNull] IReadOnlyList selfIdentifierValueComparers, + [CanBeNull] IReadOnlyList? parentIdentifierValueComparers, + [CanBeNull] IReadOnlyList? outerIdentifierValueComparers, + [CanBeNull] IReadOnlyList? selfIdentifierValueComparers, [NotNull] Expression innerShaper, - [CanBeNull] INavigationBase navigation, + [CanBeNull] INavigationBase? navigation, [NotNull] Type elementType) { Check.NotNull(parentIdentifier, nameof(parentIdentifier)); @@ -114,17 +116,17 @@ public RelationalCollectionShaperExpression( /// /// The list of value comparers to compare parent identifier. /// - public virtual IReadOnlyList ParentIdentifierValueComparers { get; } + public virtual IReadOnlyList? ParentIdentifierValueComparers { get; } /// /// The list of value comparers to compare outer identifier. /// - public virtual IReadOnlyList OuterIdentifierValueComparers { get; } + public virtual IReadOnlyList? OuterIdentifierValueComparers { get; } /// /// The list of value comparers to compare self identifier. /// - public virtual IReadOnlyList SelfIdentifierValueComparers { get; } + public virtual IReadOnlyList? SelfIdentifierValueComparers { get; } /// /// The expression to create inner elements. @@ -134,7 +136,7 @@ public RelationalCollectionShaperExpression( /// /// The navigation if associated with the collection. /// - public virtual INavigationBase Navigation { get; } + public virtual INavigationBase? Navigation { get; } /// /// The clr type of elements of the collection. diff --git a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs index fc445de8776..cca003b9888 100644 --- a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs +++ b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -121,7 +123,7 @@ public RelationalCompiledQueryCacheKey( /// if the object is a and is for the same query, /// otherwise . /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is RelationalCompiledQueryCacheKey key && Equals(key); diff --git a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs index cc05d4b58ce..ec1298e806a 100644 --- a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs b/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs index faeb57393f0..9e4354f33e3 100644 --- a/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs @@ -14,6 +14,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -53,7 +55,7 @@ protected RelationalEntityShaperExpression( [NotNull] IEntityType entityType, [NotNull] Expression valueBufferExpression, bool nullable, - [CanBeNull] LambdaExpression materializationCondition) + [CanBeNull] LambdaExpression? materializationCondition) : base(entityType, valueBufferExpression, nullable, materializationCondition) { } @@ -106,7 +108,7 @@ protected override LambdaExpression GenerateMaterializationCondition(IEntityType // Optional dependent var body = baseCondition.Body; var valueBufferParameter = baseCondition.Parameters[0]; - Expression condition = null; + Expression? condition = null; var requiredNonPkProperties = entityType.GetProperties().Where(p => !p.IsNullable && !p.IsPrimaryKey()).ToList(); if (requiredNonPkProperties.Count > 0) { diff --git a/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs b/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs index c2027496d3b..6fdd0e07856 100644 --- a/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs +++ b/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilter.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilterDependencies.cs b/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilterDependencies.cs index 0fad0324095..a871fda6bcd 100644 --- a/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilterDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalEvaluatableExpressionFilterDependencies.cs @@ -4,6 +4,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs index 9dabcb3d67a..89e92a68ab7 100644 --- a/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -46,8 +48,8 @@ public RelationalMemberTranslatorProvider([NotNull] RelationalMemberTranslatorPr } /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) diff --git a/src/EFCore.Relational/Query/RelationalMemberTranslatorProviderDependencies.cs b/src/EFCore.Relational/Query/RelationalMemberTranslatorProviderDependencies.cs index 8c9d9645383..721800b2c1d 100644 --- a/src/EFCore.Relational/Query/RelationalMemberTranslatorProviderDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalMemberTranslatorProviderDependencies.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs index 021106267e1..e29090f3798 100644 --- a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs @@ -14,6 +14,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -62,9 +64,9 @@ public RelationalMethodCallTranslatorProvider([NotNull] RelationalMethodCallTran } /// - public virtual SqlExpression Translate( + public virtual SqlExpression? Translate( IModel model, - SqlExpression instance, + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProviderDependencies.cs b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProviderDependencies.cs index a745acc0d14..ef87364bbdd 100644 --- a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProviderDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProviderDependencies.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs index 7e0cbd09702..6048f2d7ee5 100644 --- a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs +++ b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorDependencies.cs b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorDependencies.cs index df7bdd9d1f8..0a322657104 100644 --- a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorDependencies.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryCompilationContext.cs b/src/EFCore.Relational/Query/RelationalQueryCompilationContext.cs index 839a0fd92bc..0d7ef88fc1c 100644 --- a/src/EFCore.Relational/Query/RelationalQueryCompilationContext.cs +++ b/src/EFCore.Relational/Query/RelationalQueryCompilationContext.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryCompilationContextDependencies.cs b/src/EFCore.Relational/Query/RelationalQueryCompilationContextDependencies.cs index c0ace001fa7..5ad66d1907f 100644 --- a/src/EFCore.Relational/Query/RelationalQueryCompilationContextDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalQueryCompilationContextDependencies.cs @@ -4,6 +4,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryContext.cs b/src/EFCore.Relational/Query/RelationalQueryContext.cs index fe2bc4fdb47..cfe401d3f5a 100644 --- a/src/EFCore.Relational/Query/RelationalQueryContext.cs +++ b/src/EFCore.Relational/Query/RelationalQueryContext.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryContextDependencies.cs b/src/EFCore.Relational/Query/RelationalQueryContextDependencies.cs index 45dbb531eda..1f30abaebe7 100644 --- a/src/EFCore.Relational/Query/RelationalQueryContextDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalQueryContextDependencies.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs index 349e253e1ed..fbc96760bca 100644 --- a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessorDependencies.cs b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessorDependencies.cs index fe7a2e80f62..70b0f9df8f5 100644 --- a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessorDependencies.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs b/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs index bfb11480cfd..7632a570143 100644 --- a/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessor.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessorDependencies.cs b/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessorDependencies.cs index 51e2b41f256..d7f877d3a70 100644 --- a/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalQueryTranslationPreprocessorDependencies.cs @@ -4,6 +4,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index dac3deb55ab..5cf720ed993 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -16,6 +16,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -25,7 +27,6 @@ public class RelationalQueryableMethodTranslatingExpressionVisitor : QueryableMe private readonly WeakEntityExpandingExpressionVisitor _weakEntityExpandingExpressionVisitor; private readonly RelationalProjectionBindingExpressionVisitor _projectionBindingExpressionVisitor; private readonly QueryCompilationContext _queryCompilationContext; - private readonly IModel _model; private readonly ISqlExpressionFactory _sqlExpressionFactory; private readonly bool _subquery; @@ -49,7 +50,6 @@ public RelationalQueryableMethodTranslatingExpressionVisitor( var sqlExpressionFactory = relationalDependencies.SqlExpressionFactory; _queryCompilationContext = queryCompilationContext; - _model = queryCompilationContext.Model; _sqlTranslator = relationalDependencies.RelationalSqlTranslatingExpressionVisitorFactory.Create(queryCompilationContext, this); _weakEntityExpandingExpressionVisitor = new WeakEntityExpandingExpressionVisitor(_sqlTranslator, sqlExpressionFactory); _projectionBindingExpressionVisitor = new RelationalProjectionBindingExpressionVisitor(this, _sqlTranslator); @@ -82,7 +82,7 @@ protected RelationalQueryableMethodTranslatingExpressionVisitor( } /// - protected override Expression VisitExtension(Expression extensionExpression) + protected override Expression? VisitExtension(Expression extensionExpression) { switch (extensionExpression) { @@ -159,7 +159,7 @@ protected override ShapedQueryExpression CreateShapedQueryExpression(Type elemen { Check.NotNull(elementType, nameof(elementType)); - var entityType = _queryCompilationContext.Model.FindEntityType(elementType); + var entityType = _queryCompilationContext.Model.FindEntityType(elementType)!; var queryExpression = _sqlExpressionFactory.Select(entityType); return CreateShapedQueryExpression(entityType, queryExpression); @@ -185,7 +185,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent false)); /// - protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateAll(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); @@ -215,15 +215,16 @@ protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression sour } /// - protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateAny(ShapedQueryExpression source, LambdaExpression? predicate) { if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var translatedSource = TranslateWhere(source, predicate); + if (translatedSource == null) { return null; } + source = translatedSource; } var selectExpression = (SelectExpression)source.QueryExpression; @@ -244,7 +245,7 @@ protected override ShapedQueryExpression TranslateAny(ShapedQueryExpression sour } /// - protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression source, LambdaExpression selector, Type resultType) + protected override ShapedQueryExpression? TranslateAverage(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -278,7 +279,7 @@ protected override ShapedQueryExpression TranslateAverage(ShapedQueryExpression } /// - protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression source, Type resultType) + protected override ShapedQueryExpression? TranslateCast(ShapedQueryExpression source, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -289,7 +290,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou } /// - protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -300,7 +301,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s } /// - protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression source, Expression item) + protected override ShapedQueryExpression? TranslateContains(ShapedQueryExpression source, Expression item) { Check.NotNull(source, nameof(source)); Check.NotNull(item, nameof(item)); @@ -329,7 +330,7 @@ protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression } /// - protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateCount(ShapedQueryExpression source, LambdaExpression? predicate) { Check.NotNull(source, nameof(source)); @@ -338,11 +339,12 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var translatedSource = TranslateWhere(source, predicate); + if (translatedSource == null) { return null; } + source = translatedSource; } HandleGroupByForAggregate(selectExpression, eraseProjection: true); @@ -365,7 +367,7 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so } /// - protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue) + protected override ShapedQueryExpression? TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression? defaultValue) { Check.NotNull(source, nameof(source)); @@ -379,7 +381,7 @@ protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpr } /// - protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source) + protected override ShapedQueryExpression? TranslateDistinct(ShapedQueryExpression source) { Check.NotNull(source, nameof(source)); @@ -389,7 +391,7 @@ protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression } /// - protected override ShapedQueryExpression TranslateElementAtOrDefault( + protected override ShapedQueryExpression? TranslateElementAtOrDefault( ShapedQueryExpression source, Expression index, bool returnDefault) @@ -401,7 +403,7 @@ protected override ShapedQueryExpression TranslateElementAtOrDefault( } /// - protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -411,9 +413,9 @@ protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression s } /// - protected override ShapedQueryExpression TranslateFirstOrDefault( + protected override ShapedQueryExpression? TranslateFirstOrDefault( ShapedQueryExpression source, - LambdaExpression predicate, + LambdaExpression? predicate, Type returnType, bool returnDefault) { @@ -422,11 +424,12 @@ protected override ShapedQueryExpression TranslateFirstOrDefault( if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var translatedSource = TranslateWhere(source, predicate); + if (translatedSource == null) { return null; } + source = translatedSource; } var selectExpression = (SelectExpression)source.QueryExpression; @@ -436,7 +439,7 @@ protected override ShapedQueryExpression TranslateFirstOrDefault( _queryCompilationContext.Logger.FirstWithoutOrderByAndFilterWarning(); } - selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(1))); + selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(1))!); return source.ShaperExpression.Type != returnType ? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType)) @@ -444,11 +447,11 @@ protected override ShapedQueryExpression TranslateFirstOrDefault( } /// - protected override ShapedQueryExpression TranslateGroupBy( + protected override ShapedQueryExpression? TranslateGroupBy( ShapedQueryExpression source, LambdaExpression keySelector, - LambdaExpression elementSelector, - LambdaExpression resultSelector) + LambdaExpression? elementSelector, + LambdaExpression? resultSelector) { Check.NotNull(source, nameof(source)); Check.NotNull(keySelector, nameof(keySelector)); @@ -491,7 +494,7 @@ protected override ShapedQueryExpression TranslateGroupBy( return null; } - private Expression TranslateGroupingKey(Expression expression) + private Expression? TranslateGroupingKey(Expression expression) { switch (expression) { @@ -501,7 +504,7 @@ private Expression TranslateGroupingKey(Expression expression) return newExpression; } - var newArguments = new Expression[newExpression.Arguments.Count]; + var newArguments = new Expression?[newExpression.Arguments.Count]; for (var i = 0; i < newArguments.Length; i++) { newArguments[i] = TranslateGroupingKey(newExpression.Arguments[i]); @@ -514,7 +517,7 @@ private Expression TranslateGroupingKey(Expression expression) return newExpression.Update(newArguments); case MemberInitExpression memberInitExpression: - var updatedNewExpression = (NewExpression)TranslateGroupingKey(memberInitExpression.NewExpression); + var updatedNewExpression = (NewExpression?)TranslateGroupingKey(memberInitExpression.NewExpression); if (updatedNewExpression == null) { return null; @@ -549,7 +552,7 @@ private Expression TranslateGroupingKey(Expression expression) } /// - protected override ShapedQueryExpression TranslateGroupJoin( + protected override ShapedQueryExpression? TranslateGroupJoin( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, @@ -566,7 +569,7 @@ protected override ShapedQueryExpression TranslateGroupJoin( } /// - protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -577,7 +580,7 @@ protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpressio } /// - protected override ShapedQueryExpression TranslateJoin( + protected override ShapedQueryExpression? TranslateJoin( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, @@ -604,7 +607,7 @@ protected override ShapedQueryExpression TranslateJoin( } /// - protected override ShapedQueryExpression TranslateLeftJoin( + protected override ShapedQueryExpression? TranslateLeftJoin( ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, @@ -639,11 +642,12 @@ private SqlExpression CreateJoinPredicate( var outerKey = RemapLambdaBody(outer, outerKeySelector); var innerKey = RemapLambdaBody(inner, innerKeySelector); - if (outerKey is NewExpression outerNew) + if (outerKey is NewExpression outerNew + && outerNew.Arguments.Count > 0) { var innerNew = (NewExpression)innerKey; - SqlExpression result = null; + SqlExpression? result = null; for (var i = 0; i < outerNew.Arguments.Count; i++) { var joinPredicate = CreateJoinPredicate(outerNew.Arguments[i], innerNew.Arguments[i]); @@ -655,23 +659,23 @@ private SqlExpression CreateJoinPredicate( if (outerNew.Arguments.Count == 1) { result = _sqlExpressionFactory.AndAlso( - result, + result!, CreateJoinPredicate(Expression.Constant(true), Expression.Constant(true))); } - return result; + return result!; } return CreateJoinPredicate(outerKey, innerKey); } private SqlExpression CreateJoinPredicate(Expression outerKey, Expression innerKey) - => TranslateExpression(Expression.Equal(outerKey, innerKey)); + => TranslateExpression(Expression.Equal(outerKey, innerKey))!; /// - protected override ShapedQueryExpression TranslateLastOrDefault( + protected override ShapedQueryExpression? TranslateLastOrDefault( ShapedQueryExpression source, - LambdaExpression predicate, + LambdaExpression? predicate, Type returnType, bool returnDefault) { @@ -687,15 +691,16 @@ protected override ShapedQueryExpression TranslateLastOrDefault( if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var translatedSource = TranslateWhere(source, predicate); + if (translatedSource == null) { return null; } + source = translatedSource; } selectExpression.ReverseOrderings(); - selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(1))); + selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(1))!); return source.ShaperExpression.Type != returnType ? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType)) @@ -703,7 +708,7 @@ protected override ShapedQueryExpression TranslateLastOrDefault( } /// - protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateLongCount(ShapedQueryExpression source, LambdaExpression? predicate) { Check.NotNull(source, nameof(source)); @@ -712,11 +717,12 @@ protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpressio if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var translatedSource = TranslateWhere(source, predicate); + if (translatedSource == null) { return null; } + source = translatedSource; } HandleGroupByForAggregate(selectExpression, eraseProjection: true); @@ -739,7 +745,7 @@ protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpressio } /// - protected override ShapedQueryExpression TranslateMax(ShapedQueryExpression source, LambdaExpression selector, Type resultType) + protected override ShapedQueryExpression? TranslateMax(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); @@ -771,7 +777,7 @@ protected override ShapedQueryExpression TranslateMax(ShapedQueryExpression sour } /// - protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression source, LambdaExpression selector, Type resultType) + protected override ShapedQueryExpression? TranslateMin(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); @@ -803,7 +809,7 @@ protected override ShapedQueryExpression TranslateMin(ShapedQueryExpression sour } /// - protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression source, Type resultType) + protected override ShapedQueryExpression? TranslateOfType(ShapedQueryExpression source, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -859,7 +865,7 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s } /// - protected override ShapedQueryExpression TranslateOrderBy( + protected override ShapedQueryExpression? TranslateOrderBy( ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) @@ -879,7 +885,7 @@ protected override ShapedQueryExpression TranslateOrderBy( } /// - protected override ShapedQueryExpression TranslateReverse(ShapedQueryExpression source) + protected override ShapedQueryExpression? TranslateReverse(ShapedQueryExpression source) { Check.NotNull(source, nameof(source)); @@ -919,7 +925,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s } /// - protected override ShapedQueryExpression TranslateSelectMany( + protected override ShapedQueryExpression? TranslateSelectMany( ShapedQueryExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector) @@ -949,11 +955,12 @@ protected override ShapedQueryExpression TranslateSelectMany( { if (defaultIfEmpty) { - inner = TranslateDefaultIfEmpty(inner, null); - if (inner == null) + var translatedInner = TranslateDefaultIfEmpty(inner, null); + if (translatedInner == null) { return null; } + inner = translatedInner; } var innerSelectExpression = (SelectExpression)source.QueryExpression; @@ -968,7 +975,7 @@ protected override ShapedQueryExpression TranslateSelectMany( private sealed class CorrelationFindingExpressionVisitor : ExpressionVisitor { - private ParameterExpression _outerParameter; + private ParameterExpression? _outerParameter; private bool _correlated; private bool _defaultIfEmpty; @@ -1014,7 +1021,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } /// - protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) + protected override ShapedQueryExpression? TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) { Check.NotNull(source, nameof(source)); Check.NotNull(selector, nameof(selector)); @@ -1027,9 +1034,9 @@ protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpressi } /// - protected override ShapedQueryExpression TranslateSingleOrDefault( + protected override ShapedQueryExpression? TranslateSingleOrDefault( ShapedQueryExpression source, - LambdaExpression predicate, + LambdaExpression? predicate, Type returnType, bool returnDefault) { @@ -1038,15 +1045,16 @@ protected override ShapedQueryExpression TranslateSingleOrDefault( if (predicate != null) { - source = TranslateWhere(source, predicate); - if (source == null) + var translatedSource = TranslateWhere(source, predicate); + if (translatedSource == null) { return null; } + source = translatedSource; } var selectExpression = (SelectExpression)source.QueryExpression; - selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(_subquery ? 1 : 2))); + selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(_subquery ? 1 : 2))!); return source.ShaperExpression.Type != returnType ? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType)) @@ -1054,7 +1062,7 @@ protected override ShapedQueryExpression TranslateSingleOrDefault( } /// - protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression source, Expression count) + protected override ShapedQueryExpression? TranslateSkip(ShapedQueryExpression source, Expression count) { Check.NotNull(source, nameof(source)); Check.NotNull(count, nameof(count)); @@ -1077,7 +1085,7 @@ protected override ShapedQueryExpression TranslateSkip(ShapedQueryExpression sou } /// - protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateSkipWhile(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); @@ -1086,7 +1094,7 @@ protected override ShapedQueryExpression TranslateSkipWhile(ShapedQueryExpressio } /// - protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression source, LambdaExpression selector, Type resultType) + protected override ShapedQueryExpression? TranslateSum(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); @@ -1120,7 +1128,7 @@ protected override ShapedQueryExpression TranslateSum(ShapedQueryExpression sour } /// - protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression source, Expression count) + protected override ShapedQueryExpression? TranslateTake(ShapedQueryExpression source, Expression count) { Check.NotNull(source, nameof(source)); Check.NotNull(count, nameof(count)); @@ -1143,7 +1151,7 @@ protected override ShapedQueryExpression TranslateTake(ShapedQueryExpression sou } /// - protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateTakeWhile(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); @@ -1152,7 +1160,7 @@ protected override ShapedQueryExpression TranslateTakeWhile(ShapedQueryExpressio } /// - protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) + protected override ShapedQueryExpression? TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { Check.NotNull(source, nameof(source)); Check.NotNull(keySelector, nameof(keySelector)); @@ -1169,7 +1177,7 @@ protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression s } /// - protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2) + protected override ShapedQueryExpression? TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2) { Check.NotNull(source1, nameof(source1)); Check.NotNull(source2, nameof(source2)); @@ -1179,7 +1187,7 @@ protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression so } /// - protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate) + protected override ShapedQueryExpression? TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate) { Check.NotNull(source, nameof(source)); Check.NotNull(predicate, nameof(predicate)); @@ -1195,7 +1203,7 @@ protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression so return source; } - private SqlExpression TranslateExpression(Expression expression) + private SqlExpression? TranslateExpression(Expression expression) { var translation = _sqlTranslator.Translate(expression); if (translation == null && _sqlTranslator.TranslationErrorDetails != null) @@ -1206,7 +1214,7 @@ private SqlExpression TranslateExpression(Expression expression) return translation; } - private SqlExpression TranslateLambdaExpression( + private SqlExpression? TranslateLambdaExpression( ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression) => TranslateExpression(RemapLambdaBody(shapedQueryExpression, lambdaExpression)); @@ -1224,21 +1232,20 @@ internal Expression ExpandWeakEntities(SelectExpression selectExpression, Expres private sealed class WeakEntityExpandingExpressionVisitor : ExpressionVisitor { - private SelectExpression _selectExpression; private readonly RelationalSqlTranslatingExpressionVisitor _sqlTranslator; private readonly ISqlExpressionFactory _sqlExpressionFactory; + private SelectExpression _selectExpression; + public WeakEntityExpandingExpressionVisitor( RelationalSqlTranslatingExpressionVisitor sqlTranslator, ISqlExpressionFactory sqlExpressionFactory) { _sqlTranslator = sqlTranslator; _sqlExpressionFactory = sqlExpressionFactory; + _selectExpression = null!; } - public string TranslationErrorDetails - => _sqlTranslator.TranslationErrorDetails; - public Expression Expand(SelectExpression selectExpression, Expression lambdaBody) { _selectExpression = selectExpression; @@ -1289,7 +1296,7 @@ protected override Expression VisitExtension(Expression extensionExpression) : base.VisitExtension(extensionExpression); } - private Expression TryExpand(Expression source, MemberIdentity member) + private Expression? TryExpand(Expression source, MemberIdentity member) { source = source.UnwrapTypeConversion(out var convertedType); if (!(source is EntityShaperExpression entityShaperExpression)) @@ -1371,7 +1378,7 @@ private Expression TryExpand(Expression source, MemberIdentity member) var entityProjectionExpression = (EntityProjectionExpression) (entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression - ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember) + ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember!) : entityShaperExpression.ValueBufferExpression); var innerShaper = entityProjectionExpression.BindNavigation(navigation); @@ -1391,7 +1398,7 @@ private Expression TryExpand(Expression source, MemberIdentity member) { // Mapped to same table // We get identifying column to figure out tableExpression to pull columns from and nullability of most principal side - var identifyingColumn = entityProjectionExpression.BindProperty(entityType.FindPrimaryKey().Properties.First()); + var identifyingColumn = entityProjectionExpression.BindProperty(entityType.FindPrimaryKey()!.Properties.First()); var principalNullable = identifyingColumn.IsNullable // Also make nullable if navigation is on derived type and and principal is TPT // Since identifying PK would be non-nullable but principal can still be null @@ -1435,7 +1442,7 @@ private Expression TryExpand(Expression source, MemberIdentity member) : foreignKey.Properties, makeNullable); - var joinPredicate = _sqlTranslator.Translate(Expression.Equal(outerKey, innerKey)); + var joinPredicate = _sqlTranslator.Translate(Expression.Equal(outerKey, innerKey))!; _selectExpression.AddLeftJoin(innerSelectExpression, joinPredicate); var leftJoinTable = ((LeftJoinExpression)_selectExpression.Tables.Last()).Table; var propertyExpressions = GetPropertyExpressionsFromJoinedTable(targetEntityType, table, leftJoinTable); @@ -1450,7 +1457,7 @@ private Expression TryExpand(Expression source, MemberIdentity member) return innerShaper; } - private static IDictionary GetPropertyExpressionFromSameTable( + private static IDictionary? GetPropertyExpressionFromSameTable( IEntityType entityType, ITableBase table, SelectExpression selectExpression, @@ -1566,9 +1573,9 @@ private static void HandleGroupByForAggregate(SelectExpression selectExpression, } } - private ShapedQueryExpression AggregateResultShaper( + private ShapedQueryExpression? AggregateResultShaper( ShapedQueryExpression source, - Expression projection, + Expression? projection, bool throwWhenEmpty, Type resultType) { diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitorDependencies.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitorDependencies.cs index 4421414aa05..70d5c283dec 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitorDependencies.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index cce1f452601..41a768e3a29 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -20,6 +20,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor @@ -84,21 +86,21 @@ private static readonly MethodInfo _collectionAccessorAddMethodInfo = typeof(IClrCollectionAccessor).GetTypeInfo().GetDeclaredMethod(nameof(IClrCollectionAccessor.Add)); private readonly RelationalShapedQueryCompilingExpressionVisitor _parentVisitor; - private readonly ISet _tags; + private readonly ISet? _tags; private readonly bool _isTracking; private readonly bool _isAsync; private readonly bool _splitQuery; private readonly bool _detailedErrorsEnabled; private readonly bool _generateCommandCache; private readonly ParameterExpression _resultCoordinatorParameter; - private readonly ParameterExpression _executionStrategyParameter; + private readonly ParameterExpression? _executionStrategyParameter; // States scoped to SelectExpression private readonly SelectExpression _selectExpression; private readonly ParameterExpression _dataReaderParameter; private readonly ParameterExpression _resultContextParameter; - private readonly ParameterExpression _indexMapParameter; - private readonly ReaderColumn[] _readerColumns; + private readonly ParameterExpression? _indexMapParameter; + private readonly ReaderColumn[]? _readerColumns; // States to materialize only once private readonly IDictionary _variableShaperMapping = new Dictionary(); @@ -112,9 +114,9 @@ private static readonly MethodInfo _collectionAccessorAddMethodInfo private readonly List _includeExpressions = new List(); // If there is collection shaper then we need to construct ValuesArray to store values temporarily in ResultContext - private List _collectionPopulatingExpressions; - private Expression _valuesArrayExpression; - private List _valuesArrayInitializers; + private List? _collectionPopulatingExpressions; + private Expression? _valuesArrayExpression; + private List? _valuesArrayInitializers; private bool _containsCollectionMaterialization; @@ -166,7 +168,7 @@ private ShaperProcessingExpressionVisitor( SelectExpression selectExpression, ParameterExpression dataReaderParameter, ParameterExpression resultContextParameter, - ReaderColumn[] readerColumns) + ReaderColumn[]? readerColumns) { _parentVisitor = parentVisitor; _resultCoordinatorParameter = resultCoordinatorParameter; @@ -214,8 +216,8 @@ private ShaperProcessingExpressionVisitor( public LambdaExpression ProcessShaper( Expression shaperExpression, - out RelationalCommandCache relationalCommandCache, - out LambdaExpression relatedDataLoaders) + out RelationalCommandCache? relationalCommandCache, + out LambdaExpression? relatedDataLoaders) { relatedDataLoaders = null; @@ -410,7 +412,7 @@ protected override Expression VisitExtension(Expression extensionExpression) if (_containsCollectionMaterialization) { - _valuesArrayInitializers.Add(entityParameter); + _valuesArrayInitializers!.Add(entityParameter); accessor = Expression.Convert( Expression.ArrayIndex( _valuesArrayExpression, @@ -438,7 +440,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _dataReaderParameter, projectionIndex, IsNullableProjection(projection), - projection.Expression.TypeMapping, + projection.Expression.TypeMapping!, projectionBindingExpression.Type); } @@ -465,7 +467,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _dataReaderParameter, projectionIndex, nullable, - projection.Expression.TypeMapping, + projection.Expression.TypeMapping!, valueParameter.Type))); if (_containsCollectionMaterialization) @@ -476,7 +478,7 @@ protected override Expression VisitExtension(Expression extensionExpression) expressionToAdd = Expression.Convert(expressionToAdd, typeof(object)); } - _valuesArrayInitializers.Add(expressionToAdd); + _valuesArrayInitializers!.Add(expressionToAdd); accessor = Expression.Convert( Expression.ArrayIndex( _valuesArrayExpression, @@ -507,7 +509,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var entityType = entity.Type; var navigation = includeExpression.Navigation; - var includingEntityType = navigation.DeclaringEntityType.ClrType; + var includingEntityType = navigation.DeclaringEntityType.ClrType!; if (includingEntityType != entityType && includingEntityType.IsAssignableFrom(entityType)) { @@ -552,7 +554,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var relatedEntityType = innerShaper.ReturnType; var inverseNavigation = navigation.Inverse; - _collectionPopulatingExpressions.Add( + _collectionPopulatingExpressions!.Add( Expression.Call( _populateIncludeCollectionMethodInfo.MakeGenericMethod(includingEntityType, relatedEntityType), collectionIdConstant, @@ -583,7 +585,7 @@ protected override Expression VisitExtension(Expression extensionExpression) { var innerProcessor = new ShaperProcessingExpressionVisitor( _parentVisitor, _resultCoordinatorParameter, - _executionStrategyParameter, relationalSplitCollectionShaperExpression.SelectExpression, _tags); + _executionStrategyParameter!, relationalSplitCollectionShaperExpression.SelectExpression, _tags!); var innerShaper = innerProcessor.ProcessShaper( relationalSplitCollectionShaperExpression.InnerShaper, out var relationalCommandCache, @@ -591,7 +593,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var entityType = entity.Type; var navigation = includeExpression.Navigation; - var includingEntityType = navigation.DeclaringEntityType.ClrType; + var includingEntityType = navigation.DeclaringEntityType.ClrType!; if (includingEntityType != entityType && includingEntityType.IsAssignableFrom(entityType)) { @@ -634,7 +636,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var relatedEntityType = innerShaper.ReturnType; var inverseNavigation = navigation.Inverse; - _collectionPopulatingExpressions.Add( + _collectionPopulatingExpressions!.Add( Expression.Call( (_isAsync ? _populateSplitIncludeCollectionAsyncMethodInfo : _populateSplitIncludeCollectionMethodInfo) .MakeGenericMethod(includingEntityType, relatedEntityType), @@ -665,9 +667,9 @@ protected override Expression VisitExtension(Expression extensionExpression) var navigationExpression = Visit(includeExpression.NavigationExpression); var entityType = entity.Type; var navigation = includeExpression.Navigation; - var includingType = navigation.DeclaringEntityType.ClrType; + var includingType = navigation.DeclaringEntityType.ClrType!; var inverseNavigation = navigation.Inverse; - var relatedEntityType = navigation.TargetEntityType.ClrType; + var relatedEntityType = navigation.TargetEntityType.ClrType!; if (includingType != entityType && includingType.IsAssignableFrom(entityType)) { @@ -745,14 +747,14 @@ protected override Expression VisitExtension(Expression extensionExpression) Expression.Constant(outerIdentifierLambda.Compile()), Expression.Constant(collectionAccessor, typeof(IClrCollectionAccessor))))); - _valuesArrayInitializers.Add(collectionParameter); + _valuesArrayInitializers!.Add(collectionParameter); accessor = Expression.Convert( Expression.ArrayIndex( _valuesArrayExpression, Expression.Constant(_valuesArrayInitializers.Count - 1)), relationalCollectionShaperExpression.Type); - _collectionPopulatingExpressions.Add( + _collectionPopulatingExpressions!.Add( Expression.Call( _populateCollectionMethodInfo.MakeGenericMethod(collectionType, elementType, relatedElementType), collectionIdConstant, @@ -786,7 +788,7 @@ protected override Expression VisitExtension(Expression extensionExpression) { var innerProcessor = new ShaperProcessingExpressionVisitor( _parentVisitor, _resultCoordinatorParameter, - _executionStrategyParameter, relationalSplitCollectionShaperExpression.SelectExpression, _tags); + _executionStrategyParameter!, relationalSplitCollectionShaperExpression.SelectExpression, _tags!); var innerShaper = innerProcessor.ProcessShaper( relationalSplitCollectionShaperExpression.InnerShaper, out var relationalCommandCache, @@ -832,14 +834,14 @@ protected override Expression VisitExtension(Expression extensionExpression) Expression.Constant(parentIdentifierLambda.Compile()), Expression.Constant(collectionAccessor, typeof(IClrCollectionAccessor))))); - _valuesArrayInitializers.Add(collectionParameter); + _valuesArrayInitializers!.Add(collectionParameter); accessor = Expression.Convert( Expression.ArrayIndex( _valuesArrayExpression, Expression.Constant(_valuesArrayInitializers.Count - 1)), relationalSplitCollectionShaperExpression.Type); - _collectionPopulatingExpressions.Add( + _collectionPopulatingExpressions!.Add( Expression.Call( (_isAsync ? _populateSplitCollectionAsyncMethodInfo : _populateSplitCollectionMethodInfo) .MakeGenericMethod(collectionType, elementType, relatedElementType), @@ -899,7 +901,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp _dataReaderParameter, projectionIndex, nullable, - projection.Expression.TypeMapping, + projection.Expression.TypeMapping!, methodCallExpression.Type, property); } @@ -961,7 +963,7 @@ private object GetProjectionIndex(ProjectionBindingExpression projectionBindingE ? ((ConstantExpression)_selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value : (projectionBindingExpression.Index != null ? (object)projectionBindingExpression.Index - : projectionBindingExpression.IndexMap); + : projectionBindingExpression.IndexMap)!; private static bool IsNullableProjection(ProjectionExpression projection) => !(projection.Expression is ColumnExpression column) || column.IsNullable; @@ -972,7 +974,7 @@ private Expression CreateGetValueExpression( bool nullable, RelationalTypeMapping typeMapping, Type type, - IPropertyBase property = null) + IPropertyBase? property = null) { Check.DebugAssert( property != null || type.IsNullableType(), "Must read nullable value from database if property is not specified."); @@ -1079,7 +1081,7 @@ private static TValue ThrowReadValueException( Exception exception, object value, Type expectedType, - IPropertyBase property = null) + IPropertyBase? property = null) { var actualType = value?.GetType(); @@ -1167,7 +1169,7 @@ private static void InitializeIncludeCollection( where TParent : class where TNavigationEntity : class, TParent { - object collection = null; + object? collection = null; if (entity is TNavigationEntity) { if (trackingQuery) @@ -1208,7 +1210,7 @@ private static void PopulateIncludeCollection where TIncludingEntity : class where TIncludedEntity : class { - var collectionMaterializationContext = resultCoordinator.Collections[collectionId]; + var collectionMaterializationContext = resultCoordinator.Collections[collectionId]!; if (collectionMaterializationContext.Parent is TIncludingEntity entity) { if (resultCoordinator.HasNext == false) @@ -1321,7 +1323,7 @@ private static void InitializeSplitIncludeCollection where TParent : class where TNavigationEntity : class, TParent { - object collection = null; + object? collection = null; if (entity is TNavigationEntity) { if (trackingQuery) @@ -1364,7 +1366,7 @@ private static void PopulateSplitIncludeCollection InitializeReaderAsync(DbContext _, bool result, CancellationTok return result; } - resultCoordinator.SetDataReader(collectionId, dataReader); + resultCoordinator.SetDataReader(collectionId, dataReader!); } - var splitQueryCollectionContext = resultCoordinator.Collections[collectionId]; - var dataReaderContext = resultCoordinator.DataReaders[collectionId]; + var splitQueryCollectionContext = resultCoordinator.Collections[collectionId]!; + var dataReaderContext = resultCoordinator.DataReaders[collectionId]!; var dbDataReader = dataReaderContext.DataReader.DbDataReader; if (splitQueryCollectionContext.Parent is TIncludingEntity entity) { @@ -1549,7 +1551,7 @@ private static void PopulateCollection( where TRelatedEntity : TElement where TCollection : class, ICollection { - var collectionMaterializationContext = resultCoordinator.Collections[collectionId]; + var collectionMaterializationContext = resultCoordinator.Collections[collectionId]!; if (collectionMaterializationContext.Collection is null) { // nothing to materialize since no collection created @@ -1683,7 +1685,7 @@ private static void PopulateSplitCollection InitializeReaderAsync(DbContext _, bool result, CancellationTok return result; } - resultCoordinator.SetDataReader(collectionId, dataReader); + resultCoordinator.SetDataReader(collectionId, dataReader!); } - var splitQueryCollectionContext = resultCoordinator.Collections[collectionId]; - var dataReaderContext = resultCoordinator.DataReaders[collectionId]; + var splitQueryCollectionContext = resultCoordinator.Collections[collectionId]!; + var dataReaderContext = resultCoordinator.DataReaders[collectionId]!; var dbDataReader = dataReaderContext.DataReader.DbDataReader; if (splitQueryCollectionContext.Collection is null) { diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs index 4dcceb1e99f..264d5522a11 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitorDependencies.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitorDependencies.cs index c755b1257ac..a8ac8c8f2b3 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitorDependencies.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs b/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs index a84fd796c34..e3f0b9a9088 100644 --- a/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// @@ -42,7 +44,7 @@ public RelationalSplitCollectionShaperExpression( [NotNull] IReadOnlyList identifierValueComparers, [NotNull] SelectExpression selectExpression, [NotNull] Expression innerShaper, - [CanBeNull] INavigationBase navigation, + [CanBeNull] INavigationBase? navigation, [NotNull] Type elementType) { Check.NotNull(parentIdentifier, nameof(parentIdentifier)); @@ -94,7 +96,7 @@ public RelationalSplitCollectionShaperExpression( /// /// The navigation if associated with the collection. /// - public virtual INavigationBase Navigation { get; } + public virtual INavigationBase? Navigation { get; } /// /// The clr type of elements of the collection. diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index 9d1b2c652ca..fb8584c9f7f 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -15,6 +15,9 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query { @@ -78,7 +81,7 @@ public RelationalSqlTranslatingExpressionVisitor( /// /// Detailed information about errors encountered during translation. /// - public virtual string TranslationErrorDetails { get; private set; } + public virtual string? TranslationErrorDetails { get; private set; } /// /// Adds detailed information about error encountered during translation. @@ -108,7 +111,7 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) /// /// An expression to translate. /// A SQL translation of the given expression. - public virtual SqlExpression Translate([NotNull] Expression expression) + public virtual SqlExpression? Translate([NotNull] Expression expression) { Check.NotNull(expression, nameof(expression)); @@ -117,7 +120,7 @@ public virtual SqlExpression Translate([NotNull] Expression expression) return TranslateInternal(expression); } - private SqlExpression TranslateInternal(Expression expression) + private SqlExpression? TranslateInternal(Expression expression) { var result = Visit(expression); @@ -151,7 +154,7 @@ private SqlExpression TranslateInternal(Expression expression) /// /// An expression to translate Average over. /// A SQL translation of Average over the given expression. - public virtual SqlExpression TranslateAverage([NotNull] SqlExpression sqlExpression) + public virtual SqlExpression? TranslateAverage([NotNull] SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -191,7 +194,7 @@ public virtual SqlExpression TranslateAverage([NotNull] SqlExpression sqlExpress /// /// An expression to translate Count over. /// A SQL translation of Count over the given expression. - public virtual SqlExpression TranslateCount([NotNull] SqlExpression sqlExpression) + public virtual SqlExpression? TranslateCount([NotNull] SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -209,7 +212,7 @@ public virtual SqlExpression TranslateCount([NotNull] SqlExpression sqlExpressio /// /// An expression to translate LongCount over. /// A SQL translation of LongCount over the given expression. - public virtual SqlExpression TranslateLongCount([NotNull] SqlExpression sqlExpression) + public virtual SqlExpression? TranslateLongCount([NotNull] SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -227,7 +230,7 @@ public virtual SqlExpression TranslateLongCount([NotNull] SqlExpression sqlExpre /// /// An expression to translate Max over. /// A SQL translation of Max over the given expression. - public virtual SqlExpression TranslateMax([NotNull] SqlExpression sqlExpression) + public virtual SqlExpression? TranslateMax([NotNull] SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -247,7 +250,7 @@ public virtual SqlExpression TranslateMax([NotNull] SqlExpression sqlExpression) /// /// An expression to translate Min over. /// A SQL translation of Min over the given expression. - public virtual SqlExpression TranslateMin([NotNull] SqlExpression sqlExpression) + public virtual SqlExpression? TranslateMin([NotNull] SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -267,7 +270,7 @@ public virtual SqlExpression TranslateMin([NotNull] SqlExpression sqlExpression) /// /// An expression to translate Sum over. /// A SQL translation of Sum over the given expression. - public virtual SqlExpression TranslateSum([NotNull] SqlExpression sqlExpression) + public virtual SqlExpression? TranslateSum([NotNull] SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -293,7 +296,7 @@ public virtual SqlExpression TranslateSum([NotNull] SqlExpression sqlExpression) } /// - protected override Expression VisitBinary(BinaryExpression binaryExpression) + protected override Expression? VisitBinary(BinaryExpression binaryExpression) { Check.NotNull(binaryExpression, nameof(binaryExpression)); @@ -331,7 +334,7 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) || binaryExpression.NodeType == ExpressionType.NotEqual) // Visited expression could be null, We need to pass MemberInitExpression && TryRewriteEntityEquality( - binaryExpression.NodeType, visitedLeft ?? left, visitedRight ?? right, equalsMethod: false, out var result)) + binaryExpression.NodeType, visitedLeft ?? left!, visitedRight ?? right!, equalsMethod: false, out var result)) { return result; } @@ -348,14 +351,14 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) || TranslationFailed(binaryExpression.Right, visitedRight, out var sqlRight) ? null : uncheckedNodeTypeVariant == ExpressionType.Coalesce - ? _sqlExpressionFactory.Coalesce(sqlLeft, sqlRight) - : (Expression)_sqlExpressionFactory.MakeBinary( + ? _sqlExpressionFactory.Coalesce(sqlLeft!, sqlRight!) + : (Expression?)_sqlExpressionFactory.MakeBinary( uncheckedNodeTypeVariant, - sqlLeft, - sqlRight, + sqlLeft!, + sqlRight!, null); - static bool TryUnwrapConvertToObject(Expression expression, out Expression operand) + static bool TryUnwrapConvertToObject(Expression expression, out Expression? operand) { if (expression is UnaryExpression convertExpression && (convertExpression.NodeType == ExpressionType.Convert @@ -372,7 +375,7 @@ static bool TryUnwrapConvertToObject(Expression expression, out Expression opera } /// - protected override Expression VisitConditional(ConditionalExpression conditionalExpression) + protected override Expression? VisitConditional(ConditionalExpression conditionalExpression) { Check.NotNull(conditionalExpression, nameof(conditionalExpression)); @@ -384,15 +387,15 @@ protected override Expression VisitConditional(ConditionalExpression conditional || TranslationFailed(conditionalExpression.IfTrue, ifTrue, out var sqlIfTrue) || TranslationFailed(conditionalExpression.IfFalse, ifFalse, out var sqlIfFalse) ? null - : _sqlExpressionFactory.Case(new[] { new CaseWhenClause(sqlTest, sqlIfTrue) }, sqlIfFalse); + : _sqlExpressionFactory.Case(new[] { new CaseWhenClause(sqlTest!, sqlIfTrue!) }, sqlIfFalse); } /// - protected override Expression VisitConstant(ConstantExpression constantExpression) + protected override Expression? VisitConstant(ConstantExpression constantExpression) => new SqlConstantExpression(Check.NotNull(constantExpression, nameof(constantExpression)), null); /// - protected override Expression VisitExtension(Expression extensionExpression) + protected override Expression? VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); @@ -421,19 +424,19 @@ protected override Expression VisitExtension(Expression extensionExpression) } /// - protected override Expression VisitInvocation(InvocationExpression invocationExpression) + protected override Expression? VisitInvocation(InvocationExpression invocationExpression) => null; /// - protected override Expression VisitLambda(Expression lambdaExpression) + protected override Expression? VisitLambda(Expression lambdaExpression) => null; /// - protected override Expression VisitListInit(ListInitExpression listInitExpression) + protected override Expression? VisitListInit(ListInitExpression listInitExpression) => null; /// - protected override Expression VisitMember(MemberExpression memberExpression) + protected override Expression? VisitMember(MemberExpression memberExpression) { Check.NotNull(memberExpression, nameof(memberExpression)); @@ -447,11 +450,11 @@ protected override Expression VisitMember(MemberExpression memberExpression) } /// - protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) + protected override Expression? VisitMemberInit(MemberInitExpression memberInitExpression) => GetConstantOrNull(Check.NotNull(memberInitExpression, nameof(memberInitExpression))); /// - protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) + protected override Expression? VisitMethodCall(MethodCallExpression methodCallExpression) { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); @@ -476,7 +479,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (methodCallExpression.Arguments[0].Type.TryGetElementType(typeof(IQueryable<>)) == null && Visit(methodCallExpression.Arguments[0]) is GroupingElementExpression groupingElementExpression) { - Expression result; + Expression? result; switch (methodCallExpression.Method.Name) { case nameof(Enumerable.Average): @@ -494,16 +497,17 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp case nameof(Enumerable.Count): if (methodCallExpression.Arguments.Count == 2) { - groupingElementExpression = ApplyPredicate( + var newGroupingElementExpression = ApplyPredicate( groupingElementExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); - if (groupingElementExpression == null) + if (newGroupingElementExpression == null) { result = null; break; } + groupingElementExpression = newGroupingElementExpression; } - result = TranslateCount(GetExpressionForAggregation(groupingElementExpression, starProjection: true)); + result = TranslateCount(GetExpressionForAggregation(groupingElementExpression, starProjection: true)!); break; case nameof(Enumerable.Distinct): @@ -517,16 +521,17 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp case nameof(Enumerable.LongCount): if (methodCallExpression.Arguments.Count == 2) { - groupingElementExpression = ApplyPredicate( + var newGroupingElementExpression = ApplyPredicate( groupingElementExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); - if (groupingElementExpression == null) + if (newGroupingElementExpression == null) { result = null; break; } + groupingElementExpression = newGroupingElementExpression; } - result = TranslateLongCount(GetExpressionForAggregation(groupingElementExpression, starProjection: true)); + result = TranslateLongCount(GetExpressionForAggregation(groupingElementExpression, starProjection: true)!); break; case nameof(Enumerable.Max): @@ -580,7 +585,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return result ?? throw new InvalidOperationException(CoreStrings.TranslationFailed(methodCallExpression.Print())); - GroupingElementExpression ApplyPredicate(GroupingElementExpression groupingElement, LambdaExpression lambdaExpression) + GroupingElementExpression? ApplyPredicate(GroupingElementExpression groupingElement, LambdaExpression lambdaExpression) { var predicate = TranslateInternal(RemapLambda(groupingElement, lambdaExpression)); @@ -602,7 +607,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE => ReplacingExpressionVisitor.Replace( lambdaExpression.Parameters[0], groupingElement.Element, lambdaExpression.Body); - SqlExpression GetExpressionForAggregation(GroupingElementExpression groupingElement, bool starProjection = false) + SqlExpression? GetExpressionForAggregation(GroupingElementExpression groupingElement, bool starProjection = false) { var selector = TranslateInternal(groupingElement.Element); if (selector == null) @@ -668,7 +673,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) var shaperExpression = subqueryTranslation.ShaperExpression; var innerExpression = shaperExpression; - Type convertedType = null; + Type? convertedType = null; if (shaperExpression is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert) { @@ -720,7 +725,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) return scalarSubqueryExpression; } - SqlExpression sqlObject = null; + SqlExpression? sqlObject = null; SqlExpression[] arguments; var method = methodCallExpression.Method; @@ -846,7 +851,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) return null; } - arguments[i] = sqlArgument; + arguments[i] = sqlArgument!; } } @@ -873,21 +878,21 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) } /// - protected override Expression VisitNew(NewExpression newExpression) + protected override Expression? VisitNew(NewExpression newExpression) => GetConstantOrNull(Check.NotNull(newExpression, nameof(newExpression))); /// - protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) + protected override Expression? VisitNewArray(NewArrayExpression newArrayExpression) => null; /// - protected override Expression VisitParameter(ParameterExpression parameterExpression) + protected override Expression? VisitParameter(ParameterExpression parameterExpression) => parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true ? new SqlParameterExpression(Check.NotNull(parameterExpression, nameof(parameterExpression)), null) : null; /// - protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) + protected override Expression? VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); @@ -953,10 +958,10 @@ SqlExpression GeneratePredicateTPT(EntityProjectionExpression entityProjectionEx return discriminatorValues.Count == 1 ? _sqlExpressionFactory.Equal( - entityProjectionExpression.DiscriminatorExpression, + entityProjectionExpression.DiscriminatorExpression!, _sqlExpressionFactory.Constant(discriminatorValues[0])) : (SqlExpression)_sqlExpressionFactory.In( - entityProjectionExpression.DiscriminatorExpression, + entityProjectionExpression.DiscriminatorExpression!, _sqlExpressionFactory.Constant(discriminatorValues), negated: false); } @@ -997,7 +1002,7 @@ static bool HasSiblings(IEntityType entityType) } /// - protected override Expression VisitUnary(UnaryExpression unaryExpression) + protected override Expression? VisitUnary(UnaryExpression unaryExpression) { Check.NotNull(unaryExpression, nameof(unaryExpression)); @@ -1019,11 +1024,11 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) switch (unaryExpression.NodeType) { case ExpressionType.Not: - return _sqlExpressionFactory.Not(sqlOperand); + return _sqlExpressionFactory.Not(sqlOperand!); case ExpressionType.Negate: case ExpressionType.NegateChecked: - return _sqlExpressionFactory.Negate(sqlOperand); + return _sqlExpressionFactory.Negate(sqlOperand!); case ExpressionType.Convert: case ExpressionType.ConvertChecked: @@ -1043,7 +1048,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) { sqlOperand = _sqlExpressionFactory.ApplyDefaultTypeMapping(sqlOperand); - return _sqlExpressionFactory.Convert(sqlOperand, unaryExpression.Type); + return _sqlExpressionFactory.Convert(sqlOperand!, unaryExpression.Type); } break; @@ -1055,7 +1060,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) return null; } - private Expression TryBindMember(Expression source, MemberIdentity member) + private Expression? TryBindMember(Expression source, MemberIdentity member) { if (!(source is EntityReferenceExpression entityReferenceExpression)) { @@ -1080,7 +1085,7 @@ private Expression TryBindMember(Expression source, MemberIdentity member) return null; } - private SqlExpression BindProperty(EntityReferenceExpression entityReferenceExpression, IProperty property) + private SqlExpression? BindProperty(EntityReferenceExpression entityReferenceExpression, IProperty property) { if (entityReferenceExpression.ParameterEntity != null) { @@ -1104,7 +1109,7 @@ private SqlExpression BindProperty(EntityReferenceExpression entityReferenceExpr else { // This has to be index map since entities cannot map to just integer index - var index = projectionBindingExpression.IndexMap[property]; + var index = projectionBindingExpression.IndexMap![property]; innerProjection = subSelectExpression.Projection[index].Expression; subSelectExpression.ClearProjection(); } @@ -1164,7 +1169,7 @@ private static Expression ConvertObjectArrayEqualityComparison(Expression left, .Aggregate((a, b) => Expression.AndAlso(a, b)); } - private static SqlConstantExpression GetConstantOrNull(Expression expression) + private static SqlConstantExpression? GetConstantOrNull(Expression expression) => CanEvaluate(expression) ? new SqlConstantExpression( Expression.Constant( @@ -1173,7 +1178,7 @@ private static SqlConstantExpression GetConstantOrNull(Expression expression) null) : null; - private bool TryRewriteContainsEntity(Expression source, Expression item, out Expression result) + private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.NotNullWhen(true)] out Expression? result) { result = null; @@ -1244,7 +1249,8 @@ when sqlParameterExpression.Name.StartsWith(QueryCompilationContext.QueryParamet return true; } - private bool TryRewriteEntityEquality(ExpressionType nodeType, Expression left, Expression right, bool equalsMethod, out Expression result) + private bool TryRewriteEntityEquality( + ExpressionType nodeType, Expression left, Expression right, bool equalsMethod, [CA.NotNullWhen(true)] out Expression? result) { var leftEntityReference = left as EntityReferenceExpression; var rightEntityReference = right as EntityReferenceExpression; @@ -1259,7 +1265,7 @@ private bool TryRewriteEntityEquality(ExpressionType nodeType, Expression left, if (IsNullSqlConstantExpression(left) || IsNullSqlConstantExpression(right)) { - var nonNullEntityReference = IsNullSqlConstantExpression(left) ? rightEntityReference : leftEntityReference; + var nonNullEntityReference = (IsNullSqlConstantExpression(left) ? rightEntityReference : leftEntityReference)!; var entityType1 = nonNullEntityReference.EntityType; if (entityType1.GetViewOrTableMappings().FirstOrDefault()?.Table.IsOptional(entityType1) == true) @@ -1424,6 +1430,7 @@ when memberInitExpression.Bindings.SingleOrDefault( } } +#nullable disable private static T ParameterValueExtractor(QueryContext context, string baseParameterName, IProperty property) { var baseParameter = context.ParameterValues[baseParameterName]; @@ -1443,6 +1450,7 @@ private static List ParameterListValueExtractor( var getter = property.GetGetter(); return baseListParameter.Select(e => e != null ? (TProperty)getter.GetClrValue(e) : (TProperty)(object)null).ToList(); } +#nullable enable private static bool CanEvaluate(Expression expression) { @@ -1470,7 +1478,7 @@ private static bool IsNullSqlConstantExpression(Expression expression) => expression is SqlConstantExpression sqlConstant && sqlConstant.Value == null; [DebuggerStepThrough] - private static bool TranslationFailed(Expression original, Expression translation, out SqlExpression castTranslation) + private static bool TranslationFailed(Expression? original, Expression? translation, out SqlExpression? castTranslation) { if (original != null && !(translation is SqlExpression)) @@ -1504,17 +1512,17 @@ private EntityReferenceExpression(EntityReferenceExpression entityReferenceExpre EntityType = entityType; } - public EntityShaperExpression ParameterEntity { get; } - public ShapedQueryExpression SubqueryEntity { get; } + public EntityShaperExpression? ParameterEntity { get; } + public ShapedQueryExpression? SubqueryEntity { get; } public IEntityType EntityType { get; } public override Type Type - => EntityType.ClrType; + => EntityType.ClrType!; public override ExpressionType NodeType => ExpressionType.Extension; - public Expression Convert(Type type) + public Expression? Convert(Type type) { if (type == typeof(object) // Ignore object conversion || type.IsAssignableFrom(Type)) // Ignore casting to base type/interface @@ -1537,7 +1545,7 @@ public GroupingElementExpression(Expression element) public Expression Element { get; private set; } public bool IsDistinct { get; private set; } - public SqlExpression Predicate { get; private set; } + public SqlExpression? Predicate { get; private set; } public GroupingElementExpression ApplyDistinct() { diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitorDependencies.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitorDependencies.cs index 9a2ff5617de..eb3c9cacb59 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitorDependencies.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index 7ec38bd5960..0e0440f60b8 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -13,6 +13,9 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query { @@ -35,7 +38,8 @@ public SqlExpressionFactory([NotNull] SqlExpressionFactoryDependencies dependenc } /// - public virtual SqlExpression ApplyDefaultTypeMapping(SqlExpression sqlExpression) + [return: CA.NotNullIfNotNull("sqlExpression")] + public virtual SqlExpression? ApplyDefaultTypeMapping(SqlExpression? sqlExpression) { return sqlExpression == null || sqlExpression.TypeMapping != null @@ -48,7 +52,8 @@ public virtual SqlExpression ApplyDefaultTypeMapping(SqlExpression sqlExpression } /// - public virtual SqlExpression ApplyTypeMapping(SqlExpression sqlExpression, RelationalTypeMapping typeMapping) + [return: CA.NotNullIfNotNull("sqlExpression")] + public virtual SqlExpression? ApplyTypeMapping(SqlExpression? sqlExpression, RelationalTypeMapping? typeMapping) { #pragma warning disable IDE0046 // Convert to conditional expression if (sqlExpression == null @@ -92,7 +97,7 @@ private SqlExpression ApplyTypeMappingOnLike(LikeExpression likeExpression) private SqlExpression ApplyTypeMappingOnCase( CaseExpression caseExpression, - RelationalTypeMapping typeMapping) + RelationalTypeMapping? typeMapping) { var whenClauses = new List(); foreach (var caseWhenClause in caseExpression.WhenClauses) @@ -110,21 +115,21 @@ private SqlExpression ApplyTypeMappingOnCase( private SqlExpression ApplyTypeMappingOnCollate( CollateExpression collateExpression, - RelationalTypeMapping typeMapping) + RelationalTypeMapping? typeMapping) => collateExpression.Update(ApplyTypeMapping(collateExpression.Operand, typeMapping)); private SqlExpression ApplyTypeMappingOnDistinct( DistinctExpression distinctExpression, - RelationalTypeMapping typeMapping) + RelationalTypeMapping? typeMapping) => distinctExpression.Update(ApplyTypeMapping(distinctExpression.Operand, typeMapping)); private SqlExpression ApplyTypeMappingOnSqlUnary( SqlUnaryExpression sqlUnaryExpression, - RelationalTypeMapping typeMapping) + RelationalTypeMapping? typeMapping) { SqlExpression operand; Type resultType; - RelationalTypeMapping resultTypeMapping; + RelationalTypeMapping? resultTypeMapping; switch (sqlUnaryExpression.OperatorType) { case ExpressionType.Equal: @@ -164,14 +169,14 @@ private SqlExpression ApplyTypeMappingOnSqlUnary( private SqlExpression ApplyTypeMappingOnSqlBinary( SqlBinaryExpression sqlBinaryExpression, - RelationalTypeMapping typeMapping) + RelationalTypeMapping? typeMapping) { var left = sqlBinaryExpression.Left; var right = sqlBinaryExpression.Right; Type resultType; - RelationalTypeMapping resultTypeMapping; - RelationalTypeMapping inferredTypeMapping; + RelationalTypeMapping? resultTypeMapping; + RelationalTypeMapping? inferredTypeMapping; switch (sqlBinaryExpression.OperatorType) { case ExpressionType.Equal: @@ -229,11 +234,11 @@ private SqlExpression ApplyTypeMappingOnSqlBinary( } /// - public virtual SqlBinaryExpression MakeBinary( + public virtual SqlBinaryExpression? MakeBinary( ExpressionType operatorType, SqlExpression left, SqlExpression right, - RelationalTypeMapping typeMapping) + RelationalTypeMapping? typeMapping) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); @@ -268,7 +273,7 @@ public virtual SqlBinaryExpression Equal(SqlExpression left, SqlExpression right Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.Equal, left, right, null); + return MakeBinary(ExpressionType.Equal, left, right, null)!; } /// @@ -277,7 +282,7 @@ public virtual SqlBinaryExpression NotEqual(SqlExpression left, SqlExpression ri Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.NotEqual, left, right, null); + return MakeBinary(ExpressionType.NotEqual, left, right, null)!; } /// @@ -286,7 +291,7 @@ public virtual SqlBinaryExpression GreaterThan(SqlExpression left, SqlExpression Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.GreaterThan, left, right, null); + return MakeBinary(ExpressionType.GreaterThan, left, right, null)!; } /// @@ -295,7 +300,7 @@ public virtual SqlBinaryExpression GreaterThanOrEqual(SqlExpression left, SqlExp Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.GreaterThanOrEqual, left, right, null); + return MakeBinary(ExpressionType.GreaterThanOrEqual, left, right, null)!; } /// @@ -304,7 +309,7 @@ public virtual SqlBinaryExpression LessThan(SqlExpression left, SqlExpression ri Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.LessThan, left, right, null); + return MakeBinary(ExpressionType.LessThan, left, right, null)!; } /// @@ -313,7 +318,7 @@ public virtual SqlBinaryExpression LessThanOrEqual(SqlExpression left, SqlExpres Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.LessThanOrEqual, left, right, null); + return MakeBinary(ExpressionType.LessThanOrEqual, left, right, null)!; } /// @@ -322,7 +327,7 @@ public virtual SqlBinaryExpression AndAlso(SqlExpression left, SqlExpression rig Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.AndAlso, left, right, null); + return MakeBinary(ExpressionType.AndAlso, left, right, null)!; } /// @@ -331,74 +336,74 @@ public virtual SqlBinaryExpression OrElse(SqlExpression left, SqlExpression righ Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.OrElse, left, right, null); + return MakeBinary(ExpressionType.OrElse, left, right, null)!; } /// - public virtual SqlBinaryExpression Add(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Add(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.Add, left, right, typeMapping); + return MakeBinary(ExpressionType.Add, left, right, typeMapping)!; } /// - public virtual SqlBinaryExpression Subtract(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Subtract(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.Subtract, left, right, typeMapping); + return MakeBinary(ExpressionType.Subtract, left, right, typeMapping)!; } /// - public virtual SqlBinaryExpression Multiply(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Multiply(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.Multiply, left, right, typeMapping); + return MakeBinary(ExpressionType.Multiply, left, right, typeMapping)!; } /// - public virtual SqlBinaryExpression Divide(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Divide(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.Divide, left, right, typeMapping); + return MakeBinary(ExpressionType.Divide, left, right, typeMapping)!; } /// - public virtual SqlBinaryExpression Modulo(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Modulo(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.Modulo, left, right, typeMapping); + return MakeBinary(ExpressionType.Modulo, left, right, typeMapping)!; } /// - public virtual SqlBinaryExpression And(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression And(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.And, left, right, typeMapping); + return MakeBinary(ExpressionType.And, left, right, typeMapping)!; } /// - public virtual SqlBinaryExpression Or(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Or(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); - return MakeBinary(ExpressionType.Or, left, right, typeMapping); + return MakeBinary(ExpressionType.Or, left, right, typeMapping)!; } /// - public virtual SqlFunctionExpression Coalesce(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlFunctionExpression Coalesce(SqlExpression left, SqlExpression right, RelationalTypeMapping? typeMapping = null) { Check.NotNull(left, nameof(left)); Check.NotNull(right, nameof(right)); @@ -424,11 +429,11 @@ public virtual SqlFunctionExpression Coalesce(SqlExpression left, SqlExpression } /// - public virtual SqlUnaryExpression MakeUnary( + public virtual SqlUnaryExpression? MakeUnary( ExpressionType operatorType, SqlExpression operand, Type type, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) { Check.NotNull(operatorType, nameof(operand)); Check.NotNull(operand, nameof(operand)); @@ -444,7 +449,7 @@ public virtual SqlUnaryExpression IsNull(SqlExpression operand) { Check.NotNull(operand, nameof(operand)); - return MakeUnary(ExpressionType.Equal, operand, typeof(bool)); + return MakeUnary(ExpressionType.Equal, operand, typeof(bool))!; } /// @@ -452,16 +457,16 @@ public virtual SqlUnaryExpression IsNotNull(SqlExpression operand) { Check.NotNull(operand, nameof(operand)); - return MakeUnary(ExpressionType.NotEqual, operand, typeof(bool)); + return MakeUnary(ExpressionType.NotEqual, operand, typeof(bool))!; } /// - public virtual SqlUnaryExpression Convert(SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null) + public virtual SqlUnaryExpression Convert(SqlExpression operand, Type type, RelationalTypeMapping? typeMapping = null) { Check.NotNull(operand, nameof(operand)); Check.NotNull(type, nameof(type)); - return MakeUnary(ExpressionType.Convert, operand, type.UnwrapNullableType(), typeMapping); + return MakeUnary(ExpressionType.Convert, operand, type.UnwrapNullableType(), typeMapping)!; } /// @@ -469,7 +474,7 @@ public virtual SqlUnaryExpression Not(SqlExpression operand) { Check.NotNull(operand, nameof(operand)); - return MakeUnary(ExpressionType.Not, operand, operand.Type, operand.TypeMapping); + return MakeUnary(ExpressionType.Not, operand, operand.Type, operand.TypeMapping)!; } /// @@ -477,7 +482,7 @@ public virtual SqlUnaryExpression Negate(SqlExpression operand) { Check.NotNull(operand, nameof(operand)); - return MakeUnary(ExpressionType.Negate, operand, operand.Type, operand.TypeMapping); + return MakeUnary(ExpressionType.Negate, operand, operand.Type, operand.TypeMapping)!; } /// @@ -491,7 +496,7 @@ public virtual CaseExpression Case(SqlExpression operand, params CaseWhenClause[ } /// - public virtual CaseExpression Case(SqlExpression operand, IReadOnlyList whenClauses, SqlExpression elseResult) + public virtual CaseExpression Case(SqlExpression? operand, IReadOnlyList whenClauses, SqlExpression? elseResult) { Check.NotNull(operand, nameof(operand)); Check.NotNull(whenClauses, nameof(whenClauses)); @@ -522,7 +527,7 @@ public virtual CaseExpression Case(SqlExpression operand, IReadOnlyList - public virtual CaseExpression Case(IReadOnlyList whenClauses, SqlExpression elseResult) + public virtual CaseExpression Case(IReadOnlyList whenClauses, SqlExpression? elseResult) { Check.NotNull(whenClauses, nameof(whenClauses)); @@ -549,21 +554,23 @@ public virtual SqlFunctionExpression Function( string name, IEnumerable arguments, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) => Function( name, arguments, nullable: true, argumentsPropagateNullability: arguments.Select(a => false), returnType, typeMapping); /// [Obsolete("Use overload that explicitly specifies value for 'argumentsPropagateNullability' argument.")] public virtual SqlFunctionExpression Function( - string schema, + string? schema, string name, IEnumerable arguments, Type returnType, - RelationalTypeMapping typeMapping = null) - => Function( - schema, name, arguments, nullable: true, argumentsPropagateNullability: arguments.Select(a => false), returnType, - typeMapping); + RelationalTypeMapping? typeMapping = null) + => schema != null + ? Function( + schema, name, arguments, nullable: true, argumentsPropagateNullability: arguments.Select(a => false), returnType, typeMapping) + : Function( + name, arguments, nullable: true, argumentsPropagateNullability: arguments.Select(a => false), returnType, typeMapping); /// [Obsolete( @@ -573,7 +580,7 @@ public virtual SqlFunctionExpression Function( string name, IEnumerable arguments, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) => Function( instance, name, @@ -586,12 +593,12 @@ public virtual SqlFunctionExpression Function( /// [Obsolete("Use NiladicFunction method.")] - public virtual SqlFunctionExpression Function(string name, Type returnType, RelationalTypeMapping typeMapping = null) + public virtual SqlFunctionExpression Function(string name, Type returnType, RelationalTypeMapping? typeMapping = null) => NiladicFunction(name, nullable: true, returnType, typeMapping); /// [Obsolete("Use NiladicFunction method.")] - public virtual SqlFunctionExpression Function(string schema, string name, Type returnType, RelationalTypeMapping typeMapping = null) + public virtual SqlFunctionExpression Function(string schema, string name, Type returnType, RelationalTypeMapping? typeMapping = null) => NiladicFunction(schema, name, nullable: true, returnType, typeMapping); /// @@ -600,7 +607,7 @@ public virtual SqlFunctionExpression Function( SqlExpression instance, string name, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) => NiladicFunction(instance, name, nullable: true, instancePropagatesNullability: false, returnType, typeMapping); /// @@ -610,7 +617,7 @@ public virtual SqlFunctionExpression Function( bool nullable, IEnumerable argumentsPropagateNullability, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) { Check.NotEmpty(name, nameof(name)); Check.NotNull(arguments, nameof(arguments)); @@ -635,8 +642,9 @@ public virtual SqlFunctionExpression Function( bool nullable, IEnumerable argumentsPropagateNullability, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) { + Check.NotNull(schema, nameof(schema)); Check.NotEmpty(name, nameof(name)); Check.NotNull(arguments, nameof(arguments)); Check.NotNull(argumentsPropagateNullability, nameof(argumentsPropagateNullability)); @@ -661,7 +669,7 @@ public virtual SqlFunctionExpression Function( bool instancePropagatesNullability, IEnumerable argumentsPropagateNullability, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) { Check.NotNull(instance, nameof(instance)); Check.NotEmpty(name, nameof(name)); @@ -686,7 +694,7 @@ public virtual SqlFunctionExpression NiladicFunction( string name, bool nullable, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) { Check.NotEmpty(name, nameof(name)); Check.NotNull(returnType, nameof(returnType)); @@ -700,7 +708,7 @@ public virtual SqlFunctionExpression NiladicFunction( string name, bool nullable, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) { Check.NotEmpty(schema, nameof(schema)); Check.NotEmpty(name, nameof(name)); @@ -716,7 +724,7 @@ public virtual SqlFunctionExpression NiladicFunction( bool nullable, bool instancePropagatesNullability, Type returnType, - RelationalTypeMapping typeMapping = null) + RelationalTypeMapping? typeMapping = null) { Check.NotNull(instance, nameof(instance)); Check.NotEmpty(name, nameof(name)); @@ -762,7 +770,7 @@ public virtual InExpression In(SqlExpression item, SelectExpression subquery, bo } /// - public virtual LikeExpression Like(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar = null) + public virtual LikeExpression Like(SqlExpression match, SqlExpression pattern, SqlExpression? escapeChar = null) { Check.NotNull(match, nameof(match)); Check.NotNull(pattern, nameof(pattern)); @@ -779,11 +787,11 @@ public virtual SqlFragmentExpression Fragment(string sql) } /// - public virtual SqlConstantExpression Constant(object value, RelationalTypeMapping typeMapping = null) + public virtual SqlConstantExpression Constant(object? value, RelationalTypeMapping? typeMapping = null) => new SqlConstantExpression(Expression.Constant(value), typeMapping); /// - public virtual SelectExpression Select(SqlExpression projection) + public virtual SelectExpression Select(SqlExpression? projection) => new SelectExpression(projection); /// @@ -824,7 +832,7 @@ public virtual SelectExpression Select(IEntityType entityType, string sql, Expre return selectExpression; } - private void AddSelfConditions(SelectExpression selectExpression, IEntityType entityType, ITableBase table = null) + private void AddSelfConditions(SelectExpression selectExpression, IEntityType entityType, ITableBase? table = null) { // Add conditions if TPH var discriminatorAdded = AddDiscriminatorCondition(selectExpression, entityType); @@ -843,7 +851,7 @@ private void AddSelfConditions(SelectExpression selectExpression, IEntityType en } } - private void AddConditions(SelectExpression selectExpression, IEntityType entityType, ITableBase table = null) + private void AddConditions(SelectExpression selectExpression, IEntityType entityType, ITableBase? table = null) { AddSelfConditions(selectExpression, entityType, table); // Add inner join to principal if table sharing @@ -870,7 +878,7 @@ private void AddConditions(SelectExpression selectExpression, IEntityType entity } } - private void AddInnerJoin(SelectExpression selectExpression, IForeignKey foreignKey, ITableBase table) + private void AddInnerJoin(SelectExpression selectExpression, IForeignKey foreignKey, ITableBase? table) { var outerEntityProjection = GetMappedEntityProjectionExpression(selectExpression); var outerIsPrincipal = foreignKey.PrincipalEntityType.IsAssignableFrom(outerEntityProjection.EntityType); @@ -932,7 +940,7 @@ private void AddOptionalDependentConditions( IEntityType entityType, ITableBase table) { - SqlExpression predicate = null; + SqlExpression? predicate = null; var requiredNonPkProperties = entityType.GetProperties().Where(p => !p.IsNullable && !p.IsPrimaryKey()).ToList(); if (requiredNonPkProperties.Count > 0) { @@ -988,9 +996,7 @@ private void AddOptionalDependentConditions( var sameTable = table.EntityTypeMappings.Any(m => m.EntityType == referencingFk.DeclaringEntityType) && table.IsOptional(referencingFk.DeclaringEntityType); - AddInnerJoin( - otherSelectExpression, referencingFk, - sameTable ? table : null); + AddInnerJoin(otherSelectExpression, referencingFk, sameTable ? table : null); selectExpression.ApplyUnion(otherSelectExpression, distinct: true); } @@ -1006,7 +1012,7 @@ private SqlExpression IsNotNull(IProperty property, EntityProjectionExpression e /// [Obsolete("Use IRelationalTypeMappingSource directly.")] - public virtual RelationalTypeMapping GetTypeMappingForValue(object value) + public virtual RelationalTypeMapping GetTypeMappingForValue(object? value) => _typeMappingSource.GetMappingForValue(value); /// diff --git a/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs b/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs index c9ddb288c9b..eac04fa5f32 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/SqlExpressionVisitor.cs b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs index 298b6cbf936..ae6526e9e5e 100644 --- a/src/EFCore.Relational/Query/SqlExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query { /// diff --git a/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs index f1104cca64b..898a47440c9 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs @@ -8,6 +8,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -32,7 +34,7 @@ public class CaseExpression : SqlExpression public CaseExpression( [NotNull] SqlExpression operand, [NotNull] IReadOnlyList whenClauses, - [CanBeNull] SqlExpression elseResult = null) + [CanBeNull] SqlExpression? elseResult = null) : base(Check.NotEmpty(whenClauses, nameof(whenClauses))[0].Result.Type, whenClauses[0].Result.TypeMapping) { Check.NotNull(operand, nameof(operand)); @@ -49,7 +51,7 @@ public CaseExpression( /// A value to return if no matches, if any. public CaseExpression( [NotNull] IReadOnlyList whenClauses, - [CanBeNull] SqlExpression elseResult = null) + [CanBeNull] SqlExpression? elseResult = null) : base(Check.NotEmpty(whenClauses, nameof(whenClauses))[0].Result.Type, whenClauses[0].Result.TypeMapping) { _whenClauses.AddRange(whenClauses); @@ -59,7 +61,7 @@ public CaseExpression( /// /// The value to compare in . /// - public virtual SqlExpression Operand { get; } + public virtual SqlExpression? Operand { get; } /// /// The list of to match or evaluate condition to get result. @@ -70,14 +72,14 @@ public virtual IReadOnlyList WhenClauses /// /// The value to return if none of the matches. /// - public virtual SqlExpression ElseResult { get; } + public virtual SqlExpression? ElseResult { get; } /// protected override Expression VisitChildren(ExpressionVisitor visitor) { Check.NotNull(visitor, nameof(visitor)); - var operand = (SqlExpression)visitor.Visit(Operand); + var operand = (SqlExpression?)visitor.Visit(Operand); var changed = operand != Operand; var whenClauses = new List(); foreach (var whenClause in WhenClauses) @@ -97,7 +99,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } } - var elseResult = (SqlExpression)visitor.Visit(ElseResult); + var elseResult = (SqlExpression?)visitor.Visit(ElseResult); changed |= elseResult != ElseResult; return changed @@ -116,11 +118,11 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public virtual CaseExpression Update( - [CanBeNull] SqlExpression operand, + [CanBeNull] SqlExpression? operand, [NotNull] IReadOnlyList whenClauses, - [CanBeNull] SqlExpression elseResult) + [CanBeNull] SqlExpression? elseResult) => operand != Operand || !whenClauses.SequenceEqual(WhenClauses) || elseResult != ElseResult - ? (Operand == null + ? (operand == null ? new CaseExpression(whenClauses, elseResult) : new CaseExpression(operand, whenClauses, elseResult)) : this; @@ -158,7 +160,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is CaseExpression caseExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs b/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs index c6419239045..06c63154ea5 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -43,7 +45,7 @@ public CaseWhenClause([NotNull] SqlExpression test, [NotNull] SqlExpression resu public virtual SqlExpression Result { get; } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is CaseWhenClause caseWhenClause diff --git a/src/EFCore.Relational/Query/SqlExpressions/CollateExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CollateExpression.cs index 9af5508e4b7..23970328a37 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CollateExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CollateExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -79,7 +81,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is CollateExpression collateExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs index 84783d07f19..ba964a9aefe 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -41,7 +43,7 @@ internal ColumnExpression(IProperty property, IColumnBase column, TableExpressio internal ColumnExpression(ProjectionExpression subqueryProjection, TableExpressionBase table) : this( subqueryProjection.Alias, table, - subqueryProjection.Type, subqueryProjection.Expression.TypeMapping, + subqueryProjection.Type, subqueryProjection.Expression.TypeMapping!, IsNullableProjection(subqueryProjection)) { } @@ -94,19 +96,19 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// /// A new expression which has property set to true. public ColumnExpression MakeNullable() - => new ColumnExpression(Name, Table, Type, TypeMapping, true); + => new ColumnExpression(Name, Table, Type, TypeMapping!, true); /// protected override void Print(ExpressionPrinter expressionPrinter) { Check.NotNull(expressionPrinter, nameof(expressionPrinter)); - expressionPrinter.Append(Table.Alias).Append("."); + expressionPrinter.Append(Table.Alias!).Append("."); expressionPrinter.Append(Name); } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is ColumnExpression columnExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs index 0d595ea0b5e..b57c3ab0086 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -60,7 +62,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is CrossApplyExpression crossApplyExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs index a74aca9a8fd..26a399855ed 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -60,7 +62,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is CrossJoinExpression crossJoinExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/DistinctExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/DistinctExpression.cs index ef16ba7fdd0..09e27839bec 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/DistinctExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/DistinctExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -70,7 +72,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is DistinctExpression distinctExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs index 3605645ee6b..7b4f55d045e 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -59,7 +61,7 @@ public virtual ExceptExpression Update([NotNull] SelectExpression source1, [NotN Check.NotNull(source2, nameof(source2)); return source1 != Source1 || source2 != Source2 - ? new ExceptExpression(Alias, source1, source2, IsDistinct) + ? new ExceptExpression(Alias!, source1, source2, IsDistinct) : this; } @@ -87,7 +89,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is ExceptExpression exceptExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs index af5e6ccc6b9..39c631d31c7 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -29,7 +31,7 @@ public class ExistsExpression : SqlExpression public ExistsExpression( [NotNull] SelectExpression subquery, bool negated, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : base(typeof(bool), typeMapping) { Check.NotNull(subquery, nameof(subquery)); @@ -91,7 +93,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is ExistsExpression existsExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs index 29935de2659..08738af05d1 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -73,7 +75,7 @@ public virtual FromSqlExpression Update([NotNull] Expression arguments) Check.NotNull(arguments, nameof(arguments)); return arguments != Arguments - ? new FromSqlExpression(Alias, Sql, arguments) + ? new FromSqlExpression(Alias!, Sql, arguments) : this; } @@ -94,7 +96,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is FromSqlExpression fromSqlExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs index dc22978b44a..29b52513cae 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -34,7 +36,7 @@ public InExpression( [NotNull] SqlExpression item, bool negated, [NotNull] SelectExpression subquery, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this(Check.NotNull(item, nameof(item)), null, Check.NotNull(subquery, nameof(subquery)), negated, typeMapping) { } @@ -51,7 +53,7 @@ public InExpression( [NotNull] SqlExpression item, bool negated, [NotNull] SqlExpression values, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this(Check.NotNull(item, nameof(item)), Check.NotNull(values, nameof(values)), null, negated, typeMapping) { } @@ -67,7 +69,7 @@ public InExpression( [NotNull] SqlExpression item, [NotNull] SelectExpression subquery, bool negated, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this(Check.NotNull(item, nameof(item)), null, Check.NotNull(subquery, nameof(subquery)), negated, typeMapping) { } @@ -83,17 +85,17 @@ public InExpression( [NotNull] SqlExpression item, [NotNull] SqlExpression values, bool negated, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this(Check.NotNull(item, nameof(item)), Check.NotNull(values, nameof(values)), null, negated, typeMapping) { } private InExpression( SqlExpression item, - SqlExpression values, - SelectExpression subquery, + SqlExpression? values, + SelectExpression? subquery, bool negated, - RelationalTypeMapping typeMapping) + RelationalTypeMapping? typeMapping) : base(typeof(bool), typeMapping) { Item = item; @@ -115,12 +117,12 @@ private InExpression( /// /// The list of values to search item in. /// - public virtual SqlExpression Values { get; } + public virtual SqlExpression? Values { get; } /// /// The subquery to search item in. /// - public virtual SelectExpression Subquery { get; } + public virtual SelectExpression? Subquery { get; } /// protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -128,8 +130,8 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) Check.NotNull(visitor, nameof(visitor)); var item = (SqlExpression)visitor.Visit(Item); - var subquery = (SelectExpression)visitor.Visit(Subquery); - var values = (SqlExpression)visitor.Visit(Values); + var subquery = (SelectExpression?)visitor.Visit(Subquery); + var values = (SqlExpression?)visitor.Visit(Values); return Update(item, values, subquery); } @@ -151,8 +153,8 @@ public virtual InExpression Negate() /// This expression if no children changed, or an expression with the updated children. public virtual InExpression Update( [NotNull] SqlExpression item, - [CanBeNull] SqlExpression values, - [CanBeNull] SelectExpression subquery) + [CanBeNull] SqlExpression? values, + [CanBeNull] SelectExpression? subquery) { Check.NotNull(item, nameof(item)); @@ -207,7 +209,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is InExpression inExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs index dc3c4c3aad8..840c8916c8f 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -68,7 +70,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is InnerJoinExpression innerJoinExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs index 9f5c3cd564a..2639116cc55 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -59,7 +61,7 @@ public virtual IntersectExpression Update([NotNull] SelectExpression source1, [N Check.NotNull(source2, nameof(source2)); return source1 != Source1 || source2 != Source2 - ? new IntersectExpression(Alias, source1, source2, IsDistinct) + ? new IntersectExpression(Alias!, source1, source2, IsDistinct) : this; } @@ -87,7 +89,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is IntersectExpression intersectExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs index 8713904293e..0ef4bfd35c4 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -36,7 +38,7 @@ protected JoinExpressionBase([NotNull] TableExpressionBase table) public virtual TableExpressionBase Table { get; } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is JoinExpressionBase joinExpressionBase diff --git a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs index 3f46e73e1ef..5aa05213064 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -68,7 +70,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is LeftJoinExpression leftJoinExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs index f546c1c8241..818ab2fa571 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -30,8 +32,8 @@ public class LikeExpression : SqlExpression public LikeExpression( [NotNull] SqlExpression match, [NotNull] SqlExpression pattern, - [CanBeNull] SqlExpression escapeChar, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] SqlExpression? escapeChar, + [CanBeNull] RelationalTypeMapping? typeMapping) : base(typeof(bool), typeMapping) { Check.NotNull(match, nameof(match)); @@ -55,7 +57,7 @@ public LikeExpression( /// /// The escape chater to use in LIKE. /// - public virtual SqlExpression EscapeChar { get; } + public virtual SqlExpression? EscapeChar { get; } /// protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -64,7 +66,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) var match = (SqlExpression)visitor.Visit(Match); var pattern = (SqlExpression)visitor.Visit(Pattern); - var escapeChar = (SqlExpression)visitor.Visit(EscapeChar); + var escapeChar = (SqlExpression?)visitor.Visit(EscapeChar); return Update(match, pattern, escapeChar); } @@ -80,7 +82,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) public virtual LikeExpression Update( [NotNull] SqlExpression match, [NotNull] SqlExpression pattern, - [CanBeNull] SqlExpression escapeChar) + [CanBeNull] SqlExpression? escapeChar) { Check.NotNull(match, nameof(match)); Check.NotNull(pattern, nameof(pattern)); @@ -107,7 +109,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is LikeExpression likeExpression @@ -117,7 +119,7 @@ private bool Equals(LikeExpression likeExpression) => base.Equals(likeExpression) && Match.Equals(likeExpression.Match) && Pattern.Equals(likeExpression.Pattern) - && EscapeChar.Equals(likeExpression.EscapeChar); + && EscapeChar?.Equals(likeExpression.EscapeChar) == true; /// public override int GetHashCode() diff --git a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs index 2d59c64561a..289346f92c8 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -84,7 +86,7 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is OrderingExpression orderingExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs index 22f4d420d93..f03a9a97a66 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -60,7 +62,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is OuterApplyExpression outerApplyExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs index e8d914f6a3b..1bc5dc68f2d 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -37,7 +39,7 @@ protected PredicateJoinExpressionBase([NotNull] TableExpressionBase table, [NotN public virtual SqlExpression JoinPredicate { get; } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is PredicateJoinExpressionBase predicateJoinExpressionBase diff --git a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs index 00b778a4146..01799e62228 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -85,7 +87,7 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is ProjectionExpression projectionExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs index a6ce1b94a20..840dbb55467 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -29,9 +31,9 @@ public class RowNumberExpression : SqlExpression /// A list of ordering expressions to order by. /// The associated with the expression. public RowNumberExpression( - [CanBeNull] IReadOnlyList partitions, + [CanBeNull] IReadOnlyList? partitions, [NotNull] IReadOnlyList orderings, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : base(typeof(long), typeMapping) { Check.NotEmpty(orderings, nameof(orderings)); @@ -85,7 +87,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public virtual RowNumberExpression Update( - [CanBeNull] IReadOnlyList partitions, + [CanBeNull] IReadOnlyList? partitions, [NotNull] IReadOnlyList orderings) { Check.NotNull(orderings, nameof(orderings)); @@ -115,7 +117,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is RowNumberExpression rowNumberExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs index aaad51b0574..d72007687a8 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -86,7 +88,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is ScalarSubqueryExpression scalarSubqueryExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 51e4e57e795..a8921c30beb 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -13,6 +13,9 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { @@ -59,7 +62,7 @@ private readonly IDictionary _childIdentifiers = new List<(ColumnExpression Column, ValueComparer Comparer)>(); - private readonly List _pendingCollections = new List(); + private readonly List _pendingCollections = new List(); private List _tptLeftJoinTables = new List(); private IDictionary _projectionMapping = new Dictionary(); @@ -96,22 +99,22 @@ public IReadOnlyList Orderings /// /// The WHERE predicate for the SELECT. /// - public SqlExpression Predicate { get; private set; } + public SqlExpression? Predicate { get; private set; } /// /// The HAVING predicate for the SELECT when clause exists. /// - public SqlExpression Having { get; private set; } + public SqlExpression? Having { get; private set; } /// /// The limit applied to the number of rows in the result set. /// - public SqlExpression Limit { get; private set; } + public SqlExpression? Limit { get; private set; } /// /// The offset to skip rows from the result set. /// - public SqlExpression Offset { get; private set; } + public SqlExpression? Offset { get; private set; } /// /// A bool value indicating if DISTINCT is applied to projection of this . @@ -130,7 +133,7 @@ public void ApplyTags([NotNull] ISet tags) } private SelectExpression( - string alias, + string? alias, List projections, List tables, List groupBy, @@ -143,7 +146,7 @@ private SelectExpression( _orderings = orderings; } - internal SelectExpression(SqlExpression projection) + internal SelectExpression(SqlExpression? projection) : base(null) { if (projection != null) @@ -184,19 +187,20 @@ internal SelectExpression(IEntityType entityType, ISqlExpressionFactory sqlExpre var entityProjection = new EntityProjectionExpression(entityType, propertyExpressions); _projectionMapping[new ProjectionMember()] = entityProjection; - if (entityType.FindPrimaryKey() != null) + var primaryKey = entityType.FindPrimaryKey(); + if (primaryKey != null) { - foreach (var property in entityType.FindPrimaryKey().Properties) + foreach (var property in primaryKey.Properties) { - _identifier.Add((propertyExpressions[property], property.GetKeyValueComparer())); + _identifier.Add((propertyExpressions[property], property.GetKeyValueComparer()!)); } } } else { // TPT - var keyProperties = entityType.FindPrimaryKey().Properties; - List joinColumns = null; + var keyProperties = entityType.FindPrimaryKey()!.Properties; + List joinColumns = default!; var tables = new List(); var columns = new Dictionary(); foreach (var baseType in entityType.GetAllBaseTypesInclusive()) @@ -217,7 +221,7 @@ internal SelectExpression(IEntityType entityType, ISqlExpressionFactory sqlExpre { var columnExpression = columns[property]; joinColumns.Add(columnExpression); - _identifier.Add((columnExpression, property.GetKeyValueComparer())); + _identifier.Add((columnExpression, property.GetKeyValueComparer()!)); } } else @@ -298,11 +302,12 @@ internal SelectExpression(IEntityType entityType, TableExpressionBase tableExpre var entityProjection = new EntityProjectionExpression(entityType, propertyExpressions); _projectionMapping[new ProjectionMember()] = entityProjection; - if (entityType.FindPrimaryKey() != null) + var primaryKey = entityType.FindPrimaryKey(); + if (primaryKey != null) { - foreach (var property in entityType.FindPrimaryKey().Properties) + foreach (var property in primaryKey.Properties) { - _identifier.Add((propertyExpressions[property], property.GetKeyValueComparer())); + _identifier.Add((propertyExpressions[property], property.GetKeyValueComparer()!)); } } } @@ -424,7 +429,7 @@ public int AddToProjection([NotNull] SqlExpression sqlExpression) return AddToProjection(sqlExpression, null); } - private int AddToProjection(SqlExpression sqlExpression, string alias) + private int AddToProjection(SqlExpression sqlExpression, string? alias) { var existingIndex = _projection.FindIndex(pe => pe.Expression.Equals(sqlExpression)); if (existingIndex != -1) @@ -900,7 +905,7 @@ private void ApplySetOperation(SetOperationType setOperationType, SelectExpressi var innerColumn2 = (SqlExpression)joinedMapping.Value2; // For now, make sure that both sides output the same store type, otherwise the query may fail. // TODO: with #15586 we'll be able to also allow different store types which are implicitly convertible to one another. - if (innerColumn1.TypeMapping.StoreType != innerColumn2.TypeMapping.StoreType) + if (innerColumn1.TypeMapping!.StoreType != innerColumn2.TypeMapping!.StoreType) { throw new InvalidOperationException(RelationalStrings.SetOperationsOnDifferentStoreTypes); } @@ -956,7 +961,8 @@ void HandleEntityProjection( } var discriminatorExpression = projection1.DiscriminatorExpression; - if (projection1.DiscriminatorExpression != null) + if (projection1.DiscriminatorExpression != null + && projection2.DiscriminatorExpression != null) { discriminatorExpression = GenerateDiscriminatorExpression( select1, projection1.DiscriminatorExpression, @@ -1031,7 +1037,7 @@ static bool IsNullableProjection(ProjectionExpression projectionExpression) }; } - private ColumnExpression GenerateOuterColumn(SqlExpression projection, string alias = null) + private ColumnExpression GenerateOuterColumn(SqlExpression projection, string? alias = null) { var index = AddToProjection(projection, alias); return new ColumnExpression(_projection[index], this); @@ -1054,7 +1060,7 @@ public IDictionary PushdownIntoSubquery() _tptLeftJoinTables = _tptLeftJoinTables }; - _tptLeftJoinTables = null; + _tptLeftJoinTables = new List(); var projectionMap = new Dictionary(); // Projections may be present if added by lifting SingleResult/Enumerable in projection through join @@ -1190,7 +1196,7 @@ EntityProjectionExpression LiftEntityProjectionFromSubquery(EntityProjectionExpr propertyExpressions[property] = outerColumn; } - ColumnExpression discriminatorExpression = null; + ColumnExpression? discriminatorExpression = null; if (entityProjection.DiscriminatorExpression != null) { discriminatorExpression = subquery.GenerateOuterColumn( @@ -1234,7 +1240,7 @@ public Expression AddSingleProjection([NotNull] ShapedQueryExpression shapedQuer var innerExpression = RemoveConvert(shaperExpression); if (!(innerExpression is EntityShaperExpression)) { - var sentinelExpression = innerSelectExpression.Limit; + var sentinelExpression = innerSelectExpression.Limit!; var sentinelNullableType = sentinelExpression.Type.MakeNullable(); ProjectionBindingExpression dummyProjection; if (innerSelectExpression.Projection.Any()) @@ -1331,7 +1337,7 @@ static Expression RemoveConvert(Expression expression) /// A which represents shaping of this collection. public CollectionShaperExpression AddCollectionProjection( [NotNull] ShapedQueryExpression shapedQueryExpression, - [CanBeNull] INavigationBase navigation, + [CanBeNull] INavigationBase? navigation, [NotNull] Type elementType) { Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); @@ -1356,18 +1362,18 @@ public CollectionShaperExpression AddCollectionProjection( /// The type of the element in the collection. /// A value indicating whether the collection query would be run with a different DbCommand. /// An expression which represents shaping of this collection. - public Expression ApplyCollectionJoin( + public Expression? ApplyCollectionJoin( int collectionIndex, int collectionId, [NotNull] Expression innerShaper, - [CanBeNull] INavigationBase navigation, + [CanBeNull] INavigationBase? navigation, [NotNull] Type elementType, bool splitQuery = false) { Check.NotNull(innerShaper, nameof(innerShaper)); Check.NotNull(elementType, nameof(elementType)); - var innerSelectExpression = _pendingCollections[collectionIndex]; + var innerSelectExpression = _pendingCollections[collectionIndex]!; _pendingCollections[collectionIndex] = null; if (_identifier.Count == 0 @@ -1586,7 +1592,7 @@ public Expression ApplyCollectionJoin( foreach (var projection in innerSelectExpression._projectionMapping) { var value = ((ConstantExpression)projection.Value).Value; - object mappedValue = null; + object? mappedValue = null; if (value is int index) { mappedValue = indexMap[index]; @@ -1602,7 +1608,7 @@ public Expression ApplyCollectionJoin( mappedValue = newEntityIndexMap; } - mapping[projection.Key] = mappedValue; + mapping[projection.Key] = mappedValue!; } innerShaper = remapper.RemapProjectionMember(innerShaper, mapping, pendingCollectionOffset: 0); @@ -1685,7 +1691,7 @@ private static SqlExpression MakeNullable(SqlExpression sqlExpression) return (NewArrayInit(typeof(object), updatedExpressions), comparers); } - private SqlExpression TryExtractJoinKey(SelectExpression selectExpression, bool allowNonEquality) + private SqlExpression? TryExtractJoinKey(SelectExpression selectExpression, bool allowNonEquality) { if (selectExpression.Limit == null && selectExpression.Offset == null @@ -1712,12 +1718,12 @@ private SqlExpression TryExtractJoinKey(SelectExpression selectExpression, bool return null; } - private SqlExpression TryExtractJoinKey( + private SqlExpression? TryExtractJoinKey( SelectExpression selectExpression, SqlExpression predicate, List columnExpressions, bool allowNonEquality, - out SqlExpression updatedPredicate) + out SqlExpression? updatedPredicate) { if (predicate is SqlBinaryExpression sqlBinaryExpression) { @@ -1747,14 +1753,14 @@ private SqlExpression TryExtractJoinKey( return null; } - private static SqlExpression CombineNonNullExpressions(SqlExpression left, SqlExpression right) + private static SqlExpression? CombineNonNullExpressions(SqlExpression? left, SqlExpression? right) => left != null ? right != null ? new SqlBinaryExpression(ExpressionType.AndAlso, left, right, left.Type, left.TypeMapping) : left : right; - private SqlBinaryExpression ValidateKeyComparison( + private SqlBinaryExpression? ValidateKeyComparison( SelectExpression inner, SqlBinaryExpression sqlBinaryExpression, List columnExpressions, @@ -1819,7 +1825,7 @@ private SqlBinaryExpression ValidateKeyComparison( return null; } - private SqlExpression RemoveRedundantNullChecks(SqlExpression predicate, List columnExpressions) + private SqlExpression? RemoveRedundantNullChecks(SqlExpression predicate, List columnExpressions) { if (predicate is SqlBinaryExpression sqlBinaryExpression) { @@ -1866,7 +1872,8 @@ public bool ContainsOuterReference(SelectExpression selectExpression) return _containsOuterReference; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { if (_containsOuterReference) { @@ -1915,7 +1922,7 @@ private Expression AddJoin( SelectExpression innerSelectExpression, Expression outerShaper, Expression innerShaper, - SqlExpression joinPredicate = null) + SqlExpression? joinPredicate = null) { var pendingCollectionOffset = _pendingCollections.Count; AddJoin(joinType, ref innerSelectExpression, joinPredicate); @@ -2062,13 +2069,13 @@ private sealed class ProjectionBindingExpressionRemappingExpressionVisitor : Exp private readonly Expression _queryExpression; // Shifting PMs, converting PMs to index/indexMap - private IDictionary _projectionMemberMappings; + private IDictionary? _projectionMemberMappings; // Relocating index - private int[] _indexMap; + private int[]? _indexMap; // Shift pending collection offset - private int _pendingCollectionOffset; + private int? _pendingCollectionOffset; public ProjectionBindingExpressionRemappingExpressionVisitor(Expression queryExpression) { @@ -2110,7 +2117,7 @@ private CollectionShaperExpression Remap(CollectionShaperExpression collectionSh => new CollectionShaperExpression( new ProjectionBindingExpression( _queryExpression, - ((ProjectionBindingExpression)collectionShaperExpression.Projection).Index.Value + _pendingCollectionOffset, + ((ProjectionBindingExpression)collectionShaperExpression.Projection).Index!.Value + (int)_pendingCollectionOffset!, typeof(object)), collectionShaperExpression.InnerShaper, collectionShaperExpression.Navigation, @@ -2126,7 +2133,7 @@ private ProjectionBindingExpression Remap(ProjectionBindingExpression projection } var indexMap = new Dictionary(); - foreach (var item in projectionBindingExpression.IndexMap) + foreach (var item in projectionBindingExpression.IndexMap!) { indexMap[item.Key] = _indexMap[item.Value]; } @@ -2135,7 +2142,7 @@ private ProjectionBindingExpression Remap(ProjectionBindingExpression projection } var currentProjectionMember = projectionBindingExpression.ProjectionMember; - var newBinding = _projectionMemberMappings[currentProjectionMember]; + var newBinding = _projectionMemberMappings![currentProjectionMember!]; return CreateNewBinding(newBinding, projectionBindingExpression.Type); } @@ -2157,7 +2164,7 @@ private ProjectionBindingExpression CreateNewBinding(object binding, Type type) private void AddJoin( JoinType joinType, ref SelectExpression innerSelectExpression, - SqlExpression joinPredicate = null) + SqlExpression? joinPredicate = null) { // Try to convert Apply to normal join if (joinType == JoinType.CrossApply @@ -2200,7 +2207,7 @@ private void AddJoin( : new[] { new OrderingExpression(new SqlFragmentExpression("(SELECT 1)"), true) }; var rowNumberExpression = new RowNumberExpression( - partitions, orderings.ToList(), (limit ?? offset).TypeMapping); + partitions, orderings.ToList(), (limit ?? offset)!.TypeMapping); innerSelectExpression.ClearOrdering(); var projectionMappings = innerSelectExpression.PushdownIntoSubquery(); @@ -2209,8 +2216,8 @@ private void AddJoin( joinPredicate = new SqlRemappingVisitor(projectionMappings, subquery).Remap(joinPredicate); var outerColumn = subquery.GenerateOuterColumn(rowNumberExpression, "row"); - SqlExpression offsetPredicate = null; - SqlExpression limitPredicate = null; + SqlExpression? offsetPredicate = null; + SqlExpression? limitPredicate = null; if (offset != null) { offsetPredicate = new SqlBinaryExpression( @@ -2239,7 +2246,7 @@ private void AddJoin( ExpressionType.AndAlso, offsetPredicate, limitPredicate, typeof(bool), joinPredicate.TypeMapping) : offsetPredicate : limitPredicate; - innerSelectExpression.ApplyPredicate(predicate); + innerSelectExpression.ApplyPredicate(predicate!); } joinType = joinType == JoinType.CrossApply ? JoinType.InnerJoin : JoinType.LeftJoin; @@ -2311,8 +2318,8 @@ private void AddJoin( var joinTable = joinType switch { - JoinType.InnerJoin => new InnerJoinExpression(innerTable, joinPredicate), - JoinType.LeftJoin => new LeftJoinExpression(innerTable, joinPredicate), + JoinType.InnerJoin => new InnerJoinExpression(innerTable, joinPredicate!), + JoinType.LeftJoin => new LeftJoinExpression(innerTable, joinPredicate!), JoinType.CrossJoin => new CrossJoinExpression(innerTable), JoinType.CrossApply => new CrossApplyExpression(innerTable), JoinType.OuterApply => (TableExpressionBase)new OuterApplyExpression(innerTable), @@ -2481,13 +2488,16 @@ public SqlRemappingVisitor(IDictionary mappings _mappings = mappings; } - public SqlExpression Remap(SqlExpression sqlExpression) - => (SqlExpression)Visit(sqlExpression); + [return: CA.NotNullIfNotNull("sqlExpression")] + public SqlExpression? Remap(SqlExpression? sqlExpression) + => (SqlExpression?)Visit(sqlExpression); - public SelectExpression Remap(SelectExpression sqlExpression) - => (SelectExpression)Visit(sqlExpression); + [return: CA.NotNullIfNotNull("sqlExpression")] + public SelectExpression? Remap(SelectExpression? sqlExpression) + => (SelectExpression?)Visit(sqlExpression); - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { switch (expression) { @@ -2514,7 +2524,7 @@ private void AddJoin( JoinType joinType, SelectExpression innerSelectExpression, Type transparentIdentifierType, - SqlExpression joinPredicate) + SqlExpression? joinPredicate) { AddJoin(joinType, ref innerSelectExpression, joinPredicate); @@ -2638,7 +2648,7 @@ public void AddOuterApply([NotNull] SelectExpression innerSelectExpression, [Can public SelectExpression Prune() => Prune(referencedColumns: null); - private SelectExpression Prune(IReadOnlyCollection referencedColumns = null) + private SelectExpression Prune(IReadOnlyCollection? referencedColumns = null) { if (referencedColumns != null && !IsDistinct) @@ -2665,8 +2675,8 @@ private SelectExpression Prune(IReadOnlyCollection referencedColumns = n { var table = _tables[i]; var tableAlias = table is JoinExpressionBase joinExpressionBase - ? joinExpressionBase.Table.Alias - : table.Alias; + ? joinExpressionBase.Table.Alias! + : table.Alias!; if (columnsMap[tableAlias] == null && (table is LeftJoinExpression || table is OuterApplyExpression) @@ -2693,19 +2703,19 @@ private SelectExpression Prune(IReadOnlyCollection referencedColumns = n private sealed class ColumnExpressionFindingExpressionVisitor : ExpressionVisitor { - private Dictionary> _columnReferenced; - private Dictionary> _columnsUsedInJoinCondition; + private Dictionary?>? _columnReferenced; + private Dictionary?>? _columnsUsedInJoinCondition; - public Dictionary> FindColumns(SelectExpression selectExpression) + public Dictionary?> FindColumns(SelectExpression selectExpression) { - _columnReferenced = new Dictionary>(); - _columnsUsedInJoinCondition = new Dictionary>(); + _columnReferenced = new Dictionary?>(); + _columnsUsedInJoinCondition = new Dictionary?>(); foreach (var table in selectExpression.Tables) { var tableAlias = table is JoinExpressionBase joinExpressionBase - ? joinExpressionBase.Table.Alias - : table.Alias; + ? joinExpressionBase.Table.Alias! + : table.Alias!; _columnReferenced[tableAlias] = null; } @@ -2716,34 +2726,35 @@ public Dictionary> FindColumns(SelectExpression selectEx var tableAlias = keyValuePair.Key; if (_columnReferenced[tableAlias] != null) { - _columnReferenced[tableAlias].UnionWith(_columnsUsedInJoinCondition[tableAlias]); + _columnReferenced[tableAlias]!.UnionWith(_columnsUsedInJoinCondition[tableAlias]); } } return _columnReferenced; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { switch (expression) { case ColumnExpression columnExpression: - var tableAlias = columnExpression.Table.Alias; - if (_columnReferenced.ContainsKey(tableAlias)) + var tableAlias = columnExpression.Table.Alias!; + if (_columnReferenced!.ContainsKey(tableAlias)) { if (_columnReferenced[tableAlias] == null) { _columnReferenced[tableAlias] = new HashSet(); } - _columnReferenced[tableAlias].Add(columnExpression.Name); + _columnReferenced[tableAlias]!.Add(columnExpression.Name); } // Always skip the table of ColumnExpression since it will traverse into deeper subquery return columnExpression; case LeftJoinExpression leftJoinExpression: - var leftJoinTableAlias = leftJoinExpression.Table.Alias; + var leftJoinTableAlias = leftJoinExpression.Table.Alias!; // Visiting the join predicate will add some columns for join table. // But if all the referenced columns are in join predicate only then we can remove the join table. // So if there are no referenced columns yet means there is still potential to remove this table, @@ -2752,12 +2763,12 @@ public override Expression Visit(Expression expression) // We currently do this only for LeftJoin since that is the only predicate join table we remove. // We should also remove references to the outer if this column gets removed then that subquery can also remove projections // But currently we only remove table for TPT scenario in which there are all table expressions which connects via joins. - var joinOnSameLevel = _columnReferenced.ContainsKey(leftJoinTableAlias); + var joinOnSameLevel = _columnReferenced!.ContainsKey(leftJoinTableAlias); var noReferences = !joinOnSameLevel || _columnReferenced[leftJoinTableAlias] == null; base.Visit(leftJoinExpression); if (noReferences && joinOnSameLevel) { - _columnsUsedInJoinCondition[leftJoinTableAlias] = _columnReferenced[leftJoinTableAlias]; + _columnsUsedInJoinCondition![leftJoinTableAlias] = _columnReferenced[leftJoinTableAlias]; _columnReferenced[leftJoinTableAlias] = null; } @@ -2978,7 +2989,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SelectExpression selectExpression @@ -3143,15 +3154,17 @@ public SelectExpression Update( public SelectExpression Update( [NotNull] List projections, [NotNull] List tables, - [CanBeNull] SqlExpression predicate, - [CanBeNull] List groupBy, - [CanBeNull] SqlExpression having, - [CanBeNull] List orderings, - [CanBeNull] SqlExpression limit, - [CanBeNull] SqlExpression offset) + [CanBeNull] SqlExpression? predicate, + [NotNull] List groupBy, + [CanBeNull] SqlExpression? having, + [NotNull] List orderings, + [CanBeNull] SqlExpression? limit, + [CanBeNull] SqlExpression? offset) { Check.NotNull(projections, nameof(projections)); Check.NotNull(tables, nameof(tables)); + Check.NotNull(groupBy, nameof(groupBy)); + Check.NotNull(orderings, nameof(orderings)); var projectionMapping = new Dictionary(_projectionMapping.Count); foreach (var kvp in _projectionMapping) @@ -3243,7 +3256,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) expressionPrinter.Append($"-- {tag}"); } - IDisposable indent = null; + IDisposable? indent = null; if (Alias != null) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs b/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs index ef0d246acb7..df33268023c 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs @@ -5,6 +5,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -56,7 +58,7 @@ protected SetOperationBase( public virtual SelectExpression Source2 { get; } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SetOperationBase setOperationBase diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs index 520834a780a..25affc40ed8 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -63,7 +65,7 @@ public SqlBinaryExpression( [NotNull] SqlExpression left, [NotNull] SqlExpression right, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : base(type, typeMapping) { Check.NotNull(left, nameof(left)); @@ -164,7 +166,7 @@ static bool RequiresBrackets(SqlExpression expression) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SqlBinaryExpression sqlBinaryExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs index dccc290c581..d90353c0c34 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -28,7 +30,7 @@ public class SqlConstantExpression : SqlExpression /// /// A . /// The associated with the expression. - public SqlConstantExpression([NotNull] ConstantExpression constantExpression, [CanBeNull] RelationalTypeMapping typeMapping) + public SqlConstantExpression([NotNull] ConstantExpression constantExpression, [CanBeNull] RelationalTypeMapping? typeMapping) : base(Check.NotNull(constantExpression, nameof(constantExpression)).Type.UnwrapNullableType(), typeMapping) { _constantExpression = constantExpression; @@ -45,7 +47,7 @@ public virtual object Value /// /// A relational type mapping to apply. /// A new expression which has supplied type mapping. - public virtual SqlExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping typeMapping) + public virtual SqlExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping? typeMapping) => new SqlConstantExpression(_constantExpression, typeMapping); /// @@ -68,7 +70,7 @@ private void Print(object value, ExpressionPrinter expressionPrinter) => expressionPrinter.Append(TypeMapping?.GenerateSqlLiteral(value) ?? Value?.ToString() ?? "NULL"); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SqlConstantExpression sqlConstantExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs index a6269b9588c..544e9f4bb0b 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -26,7 +28,7 @@ public abstract class SqlExpression : Expression, IPrintableExpression /// /// The of the expression. /// The associated with the expression. - protected SqlExpression([NotNull] Type type, [CanBeNull] RelationalTypeMapping typeMapping) + protected SqlExpression([NotNull] Type type, [CanBeNull] RelationalTypeMapping? typeMapping) { Check.NotNull(type, nameof(type)); @@ -42,7 +44,7 @@ protected SqlExpression([NotNull] Type type, [CanBeNull] RelationalTypeMapping t /// /// The associated with this expression. /// - public virtual RelationalTypeMapping TypeMapping { get; } + public virtual RelationalTypeMapping? TypeMapping { get; } /// protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -63,7 +65,7 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) => Print(expressionPrinter); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SqlExpression sqlExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs index 840cb1f5ac7..758503e698f 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -53,7 +55,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SqlFragmentExpression sqlFragmentExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs index e4bd4470f43..71ef190a80b 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs @@ -10,6 +10,7 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -21,6 +22,7 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions /// not used in application code. /// /// + // TODO - NULLABLE for C# 9 (MemberNotNullIf on IsNiladic) public class SqlFunctionExpression : SqlExpression { /// @@ -34,7 +36,7 @@ public SqlFunctionExpression( [NotNull] string functionName, bool nullable, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( instance: null, schema: null, functionName, nullable, instancePropagatesNullability: null, builtIn: true, type, typeMapping) { @@ -53,7 +55,7 @@ public SqlFunctionExpression( [NotNull] string functionName, bool nullable, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( instance: null, Check.NotEmpty(schema, nameof(schema)), functionName, nullable, instancePropagatesNullability: null, builtIn: false, type, typeMapping) @@ -76,7 +78,7 @@ public SqlFunctionExpression( bool nullable, bool instancePropagatesNullability, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( Check.NotNull(instance, nameof(instance)), schema: null, functionName, nullable, instancePropagatesNullability, builtIn: true, type, typeMapping) @@ -84,14 +86,14 @@ public SqlFunctionExpression( } private SqlFunctionExpression( - [CanBeNull] SqlExpression instance, - [CanBeNull] string schema, + [CanBeNull] SqlExpression? instance, + [CanBeNull] string? schema, [NotNull] string name, bool nullable, bool? instancePropagatesNullability, bool builtIn, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( instance, schema, name, niladic: true, arguments: null, nullable, instancePropagatesNullability, argumentsPropagateNullability: null, builtIn, type, typeMapping) @@ -113,7 +115,7 @@ public SqlFunctionExpression( bool nullable, [NotNull] IEnumerable argumentsPropagateNullability, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( instance: null, schema: null, functionName, arguments, nullable, instancePropagatesNullability: null, argumentsPropagateNullability, builtIn: true, type, typeMapping) @@ -131,13 +133,13 @@ public SqlFunctionExpression( /// The of the expression. /// The associated with the expression. public SqlFunctionExpression( - [CanBeNull] string schema, + [CanBeNull] string? schema, [NotNull] string functionName, [NotNull] IEnumerable arguments, bool nullable, [NotNull] IEnumerable argumentsPropagateNullability, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( instance: null, Check.NullButNotEmpty(schema, nameof(schema)), functionName, arguments, nullable, instancePropagatesNullability: null, argumentsPropagateNullability, builtIn: false, type, typeMapping) @@ -163,7 +165,7 @@ public SqlFunctionExpression( bool instancePropagatesNullability, [NotNull] IEnumerable argumentsPropagateNullability, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( Check.NotNull(instance, nameof(instance)), schema: null, functionName, arguments, nullable, instancePropagatesNullability, argumentsPropagateNullability, builtIn: true, type, typeMapping) @@ -171,8 +173,8 @@ public SqlFunctionExpression( } private SqlFunctionExpression( - [CanBeNull] SqlExpression instance, - [CanBeNull] string schema, + [CanBeNull] SqlExpression? instance, + [CanBeNull] string? schema, [NotNull] string name, [NotNull] IEnumerable arguments, bool nullable, @@ -180,7 +182,7 @@ private SqlFunctionExpression( [NotNull] IEnumerable argumentsPropagateNullability, bool builtIn, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : this( instance, schema, name, niladic: false, Check.NotNull(arguments, nameof(arguments)), nullable, instancePropagatesNullability, Check.NotNull(argumentsPropagateNullability, nameof(argumentsPropagateNullability)), builtIn, @@ -189,17 +191,17 @@ private SqlFunctionExpression( } private SqlFunctionExpression( - [CanBeNull] SqlExpression instance, - [CanBeNull] string schema, + [CanBeNull] SqlExpression? instance, + [CanBeNull] string? schema, [NotNull] string name, bool niladic, - [CanBeNull] IEnumerable arguments, + [CanBeNull] IEnumerable? arguments, bool nullable, bool? instancePropagatesNullability, - [CanBeNull] IEnumerable argumentsPropagateNullability, + [CanBeNull] IEnumerable? argumentsPropagateNullability, bool builtIn, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : base(type, typeMapping) { Check.NotEmpty(name, nameof(name)); @@ -224,7 +226,7 @@ private SqlFunctionExpression( /// /// The schema in which the function is defined, if any. /// - public virtual string Schema { get; } + public virtual string? Schema { get; } /// /// A bool value indicating if the function is niladic. @@ -239,12 +241,12 @@ private SqlFunctionExpression( /// /// The list of arguments of this function. /// - public virtual IReadOnlyList Arguments { get; } + public virtual IReadOnlyList? Arguments { get; } /// /// The instance on which this function is applied. /// - public virtual SqlExpression Instance { get; } + public virtual SqlExpression? Instance { get; } /// /// A bool value indicating if the function can return null result. @@ -260,7 +262,7 @@ private SqlFunctionExpression( /// A list of bool values indicating whether individual argument propagate null to the result. /// - public virtual IReadOnlyList ArgumentsPropagateNullability { get; } + public virtual IReadOnlyList? ArgumentsPropagateNullability { get; } /// protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -268,13 +270,13 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) Check.NotNull(visitor, nameof(visitor)); var changed = false; - var instance = (SqlExpression)visitor.Visit(Instance); + var instance = (SqlExpression?)visitor.Visit(Instance); changed |= instance != Instance; - SqlExpression[] arguments = default; + SqlExpression[]? arguments = default; if (!IsNiladic) { - arguments = new SqlExpression[Arguments.Count]; + arguments = new SqlExpression[Arguments!.Count]; for (var i = 0; i < arguments.Length; i++) { arguments[i] = (SqlExpression)visitor.Visit(Arguments[i]); @@ -303,7 +305,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// /// A relational type mapping to apply. /// A new expression which has supplied type mapping. - public virtual SqlFunctionExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping typeMapping) + public virtual SqlFunctionExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping? typeMapping) => new SqlFunctionExpression( Instance, Schema, @@ -324,7 +326,7 @@ public virtual SqlFunctionExpression ApplyTypeMapping([CanBeNull] RelationalType /// The property of the result. /// The property of the result. /// This expression if no children changed, or an expression with the updated children. - public virtual SqlFunctionExpression Update([CanBeNull] SqlExpression instance, [CanBeNull] IReadOnlyList arguments) + public virtual SqlFunctionExpression Update([CanBeNull] SqlExpression? instance, [CanBeNull] IReadOnlyList? arguments) { return instance != Instance || !arguments?.SequenceEqual(Arguments) == true ? new SqlFunctionExpression( @@ -365,13 +367,13 @@ protected override void Print(ExpressionPrinter expressionPrinter) if (!IsNiladic) { expressionPrinter.Append("("); - expressionPrinter.VisitCollection(Arguments); + expressionPrinter.VisitCollection(Arguments!); expressionPrinter.Append(")"); } } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SqlFunctionExpression sqlFunctionExpression @@ -394,9 +396,12 @@ public override int GetHashCode() hash.Add(IsNiladic); hash.Add(Schema); hash.Add(Instance); - for (var i = 0; i < Arguments.Count; i++) + if (Arguments != null) { - hash.Add(Arguments[i]); + for (var i = 0; i < Arguments.Count; i++) + { + hash.Add(Arguments[i]); + } } return hash.ToHashCode(); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs index 169affa36f8..39afc251c90 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -23,7 +25,7 @@ public sealed class SqlParameterExpression : SqlExpression { private readonly ParameterExpression _parameterExpression; - internal SqlParameterExpression(ParameterExpression parameterExpression, RelationalTypeMapping typeMapping) + internal SqlParameterExpression(ParameterExpression parameterExpression, RelationalTypeMapping? typeMapping) : base(parameterExpression.Type.UnwrapNullableType(), typeMapping) { _parameterExpression = parameterExpression; @@ -46,7 +48,7 @@ public string Name /// /// A relational type mapping to apply. /// A new expression which has supplied type mapping. - public SqlExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping typeMapping) + public SqlExpression ApplyTypeMapping([CanBeNull] RelationalTypeMapping? typeMapping) => new SqlParameterExpression(_parameterExpression, typeMapping); /// @@ -66,7 +68,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SqlParameterExpression sqlParameterExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs index 24b84e6cb62..00fd26a9288 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -46,7 +48,7 @@ public SqlUnaryExpression( ExpressionType operatorType, [NotNull] SqlExpression operand, [NotNull] Type type, - [CanBeNull] RelationalTypeMapping typeMapping) + [CanBeNull] RelationalTypeMapping? typeMapping) : base(type, typeMapping) { Check.NotNull(operand, nameof(operand)); @@ -101,7 +103,8 @@ protected override void Print(ExpressionPrinter expressionPrinter) { Check.NotNull(expressionPrinter, nameof(expressionPrinter)); - if (OperatorType == ExpressionType.Convert) + if (OperatorType == ExpressionType.Convert + && TypeMapping != null) { expressionPrinter.Append("CAST("); expressionPrinter.Visit(Operand); @@ -120,7 +123,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is SqlUnaryExpression sqlUnaryExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs index 6ea2c6bbbc2..c25c20fd88e 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -38,7 +40,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) expressionPrinter.Append(Schema).Append("."); } - expressionPrinter.Append(Name).Append(" AS ").Append(Alias); + expressionPrinter.Append(Name).Append(" AS ").Append(Alias!); } /// @@ -57,7 +59,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) public ITableBase Table { get; } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) // This should be reference equal only. => obj != null && ReferenceEquals(this, obj); diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs index cf567ef8829..32f734ae861 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -23,7 +25,7 @@ public abstract class TableExpressionBase : Expression, IPrintableExpression /// Creates a new instance of the class. /// /// A string alias for the table source. - protected TableExpressionBase([CanBeNull] string alias) + protected TableExpressionBase([CanBeNull] string? alias) { Check.NullButNotEmpty(alias, nameof(alias)); @@ -33,7 +35,7 @@ protected TableExpressionBase([CanBeNull] string alias) /// /// The alias assigned to this table source. /// - public virtual string Alias { get; internal set; } + public virtual string? Alias { get; internal set; } /// protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -62,7 +64,7 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) => Print(expressionPrinter); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is TableExpressionBase tableExpressionBase diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableValuedFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/TableValuedFunctionExpression.cs index 38abd4ee0b3..82d49816815 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableValuedFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableValuedFunctionExpression.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -50,10 +52,7 @@ private TableValuedFunctionExpression(string alias, IStoreFunction storeFunction /// /// The list of arguments of this function. /// - public virtual IReadOnlyList Arguments - { - get; - } + public virtual IReadOnlyList Arguments { get; } /// protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -69,7 +68,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } return changed - ? new TableValuedFunctionExpression(Alias, StoreFunction, arguments) + ? new TableValuedFunctionExpression(Alias!, StoreFunction, arguments) : this; } @@ -84,7 +83,7 @@ public virtual TableValuedFunctionExpression Update([NotNull] IReadOnlyList - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is TableValuedFunctionExpression tableValuedFunctionExpression diff --git a/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs index 9fc3a64af9e..31dad14d7a2 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { /// @@ -59,7 +61,7 @@ public virtual UnionExpression Update([NotNull] SelectExpression source1, [NotNu Check.NotNull(source2, nameof(source2)); return source1 != Source1 || source2 != Source2 - ? new UnionExpression(Alias, source1, source2, IsDistinct) + ? new UnionExpression(Alias!, source1, source2, IsDistinct) : this; } @@ -87,7 +89,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || obj is UnionExpression unionExpression diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index 8cb1157cfd7..113e6d0203e 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using JetBrains.Annotations; @@ -11,6 +12,9 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; + +#nullable enable namespace Microsoft.EntityFrameworkCore.Query { @@ -44,6 +48,7 @@ public SqlNullabilityProcessor( _sqlExpressionFactory = dependencies.SqlExpressionFactory; UseRelationalNulls = useRelationalNulls; _nonNullableColumns = new List(); + ParameterValues = null!; } /// @@ -321,7 +326,8 @@ protected virtual SelectExpression Visit([NotNull] SelectExpression selectExpres /// A sql expression to visit. /// A bool value indicating whether the sql expression is nullable. /// An optimized sql expression. - protected virtual SqlExpression Visit([CanBeNull] SqlExpression sqlExpression, out bool nullable) + [return: CA.NotNullIfNotNull("sqlExpression")] + protected virtual SqlExpression? Visit([CanBeNull] SqlExpression? sqlExpression, out bool nullable) => Visit(sqlExpression, allowOptimizedExpansion: false, out nullable); /// @@ -331,11 +337,13 @@ protected virtual SqlExpression Visit([CanBeNull] SqlExpression sqlExpression, o /// A bool value indicating if optimized expansion which considers null value as false value is allowed. /// A bool value indicating whether the sql expression is nullable. /// An optimized sql expression. - protected virtual SqlExpression Visit([CanBeNull] SqlExpression sqlExpression, bool allowOptimizedExpansion, out bool nullable) + [return: CA.NotNullIfNotNull("sqlExpression")] + protected virtual SqlExpression? Visit([CanBeNull] SqlExpression? sqlExpression, bool allowOptimizedExpansion, out bool nullable) => Visit(sqlExpression, allowOptimizedExpansion, preserveNonNullableColumns: false, out nullable); - private SqlExpression Visit( - [CanBeNull] SqlExpression sqlExpression, + [return: CA.NotNullIfNotNull("sqlExpression")] + private SqlExpression? Visit( + [CanBeNull] SqlExpression? sqlExpression, bool allowOptimizedExpansion, bool preserveNonNullableColumns, out bool nullable) @@ -458,7 +466,7 @@ protected virtual SqlExpression VisitCase([NotNull] CaseExpression caseExpressio } } - SqlExpression elseResult = null; + SqlExpression? elseResult = null; if (!testEvaluatesToTrue) { elseResult = Visit(caseExpression.ElseResult, out var elseResultNullable); @@ -553,7 +561,7 @@ protected virtual SqlExpression VisitExists( // if subquery has predicate which evaluates to false, we can simply return false return TryGetBoolConstantValue(subquery.Predicate) == false - ? subquery.Predicate + ? subquery.Predicate! : existsExpression.Update(subquery); } @@ -579,7 +587,7 @@ protected virtual SqlExpression VisitIn([NotNull] InExpression inExpression, boo { nullable = false; - return subquery.Predicate; + return subquery.Predicate!; } // if item is not nullable, and subquery contains a non-nullable column we know the result can never be null @@ -597,7 +605,7 @@ protected virtual SqlExpression VisitIn([NotNull] InExpression inExpression, boo if (UseRelationalNulls || !(inExpression.Values is SqlConstantExpression || inExpression.Values is SqlParameterExpression)) { - var (valuesExpression, valuesList, _) = ProcessInExpressionValues(inExpression.Values, extractNullValues: false); + var (valuesExpression, valuesList, _) = ProcessInExpressionValues(inExpression.Values!, extractNullValues: false); nullable = false; return valuesList.Count == 0 @@ -663,14 +671,14 @@ protected virtual SqlExpression VisitIn([NotNull] InExpression inExpression, boo simplifiedInExpression, _sqlExpressionFactory.IsNull(item)); - (SqlConstantExpression ProcessedValuesExpression, List ProcessedValuesList, bool HasNullValue) + (SqlConstantExpression ProcessedValuesExpression, List ProcessedValuesList, bool HasNullValue) ProcessInExpressionValues(SqlExpression valuesExpression, bool extractNullValues) { - var inValues = new List(); + var inValues = new List(); var hasNullValue = false; - RelationalTypeMapping typeMapping = null; + RelationalTypeMapping? typeMapping = null; - IEnumerable values = null; + IEnumerable? values = null; if (valuesExpression is SqlConstantExpression sqlConstant) { typeMapping = sqlConstant.TypeMapping; @@ -681,9 +689,13 @@ protected virtual SqlExpression VisitIn([NotNull] InExpression inExpression, boo DoNotCache(); typeMapping = sqlParameter.TypeMapping; values = (IEnumerable)ParameterValues[sqlParameter.Name]; + if (values == null) + { + throw new NullReferenceException(); + } } - foreach (var value in values) + foreach (var value in values!) { if (value == null && extractNullValues) { @@ -702,7 +714,7 @@ protected virtual SqlExpression VisitIn([NotNull] InExpression inExpression, boo SqlExpression SimplifyInExpression( InExpression inExpression, SqlConstantExpression inValuesExpression, - List inValuesList) + List inValuesList) { return inValuesList.Count == 1 ? inExpression.IsNegated @@ -711,7 +723,7 @@ SqlExpression SimplifyInExpression( _sqlExpressionFactory.Constant(inValuesList[0], inValuesExpression.TypeMapping)) : _sqlExpressionFactory.Equal( inExpression.Item, - _sqlExpressionFactory.Constant(inValuesList[0], inExpression.Values.TypeMapping)) + _sqlExpressionFactory.Constant(inValuesList[0], inExpression.Values!.TypeMapping)) : inExpression; } } @@ -843,12 +855,12 @@ protected virtual SqlExpression VisitSqlBinary( { if (leftNullable) { - left = AddNullConcatenationProtection(left, sqlBinaryExpression.TypeMapping); + left = AddNullConcatenationProtection(left, sqlBinaryExpression.TypeMapping!); } if (rightNullable) { - right = AddNullConcatenationProtection(right, sqlBinaryExpression.TypeMapping); + right = AddNullConcatenationProtection(right, sqlBinaryExpression.TypeMapping!); } nullable = false; @@ -972,6 +984,7 @@ protected virtual SqlExpression VisitSqlFunction( Check.NotNull(sqlFunctionExpression, nameof(sqlFunctionExpression)); if (sqlFunctionExpression.IsBuiltIn + && sqlFunctionExpression.Arguments != null && string.Equals(sqlFunctionExpression.Name, "COALESCE", StringComparison.OrdinalIgnoreCase)) { var left = Visit(sqlFunctionExpression.Arguments[0], out var leftNullable); @@ -990,7 +1003,7 @@ protected virtual SqlExpression VisitSqlFunction( return sqlFunctionExpression.Update(instance, sqlFunctionExpression.Arguments); } - var arguments = new SqlExpression[sqlFunctionExpression.Arguments.Count]; + var arguments = new SqlExpression[sqlFunctionExpression.Arguments!.Count]; for (var i = 0; i < arguments.Length; i++) { arguments[i] = Visit(sqlFunctionExpression.Arguments[i], out _); @@ -1068,7 +1081,7 @@ protected virtual SqlExpression VisitSqlUnary( : updated; } - private static bool? TryGetBoolConstantValue(SqlExpression expression) + private static bool? TryGetBoolConstantValue(SqlExpression? expression) => expression is SqlConstantExpression constantExpression && constantExpression.Value is bool boolValue ? boolValue @@ -1156,7 +1169,7 @@ private SqlExpression OptimizeComparison( if (TryGetBoolConstantValue(right) is bool rightBoolValue && !leftNullable - && left.TypeMapping.Converter == null) + && left.TypeMapping!.Converter == null) { nullable = leftNullable; @@ -1172,7 +1185,7 @@ private SqlExpression OptimizeComparison( if (TryGetBoolConstantValue(left) is bool leftBoolValue && !rightNullable - && right.TypeMapping.Converter == null) + && right.TypeMapping!.Converter == null) { nullable = rightNullable; @@ -1212,12 +1225,12 @@ private SqlExpression OptimizeComparison( if (leftNegated) { - left = leftUnary.Operand; + left = leftUnary!.Operand; } if (rightNegated) { - right = rightUnary.Operand; + right = rightUnary!.Operand; } // a == b <=> !a == !b -> a == b @@ -1254,12 +1267,12 @@ private SqlExpression RewriteNullSemantics( if (leftNegated) { - left = leftUnary.Operand; + left = leftUnary!.Operand; } if (rightNegated) { - right = rightUnary.Operand; + right = rightUnary!.Operand; } var leftIsNull = ProcessNullNotNull(_sqlExpressionFactory.IsNull(left), leftNullable); @@ -1473,7 +1486,7 @@ private SqlExpression OptimizeNonNullableNotExpression(SqlUnaryExpression sqlUna : ExpressionType.AndAlso, left, right, - sqlBinaryOperand.TypeMapping)); + sqlBinaryOperand.TypeMapping)!); } // !(a == b) -> a != b @@ -1488,7 +1501,7 @@ private SqlExpression OptimizeNonNullableNotExpression(SqlUnaryExpression sqlUna negated, sqlBinaryOperand.Left, sqlBinaryOperand.Right, - sqlBinaryOperand.TypeMapping); + sqlBinaryOperand.TypeMapping)!; } } break; @@ -1599,7 +1612,7 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, sqlUnaryExpression.OperatorType, sqlBinaryOperand.Left, typeof(bool), - sqlUnaryExpression.TypeMapping), + sqlUnaryExpression.TypeMapping)!, operandNullable); var right = ProcessNullNotNull( @@ -1607,7 +1620,7 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, sqlUnaryExpression.OperatorType, sqlBinaryOperand.Right, typeof(bool), - sqlUnaryExpression.TypeMapping), + sqlUnaryExpression.TypeMapping)!, operandNullable); return SimplifyLogicalSqlBinaryExpression( @@ -1617,7 +1630,7 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, : ExpressionType.AndAlso, left, right, - sqlUnaryExpression.TypeMapping)); + sqlUnaryExpression.TypeMapping)!); } case SqlFunctionExpression sqlFunctionExpression: @@ -1631,9 +1644,9 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, var left = ProcessNullNotNull( _sqlExpressionFactory.MakeUnary( sqlUnaryExpression.OperatorType, - sqlFunctionExpression.Arguments[0], + sqlFunctionExpression.Arguments![0], typeof(bool), - sqlUnaryExpression.TypeMapping), + sqlUnaryExpression.TypeMapping)!, operandNullable); var right = ProcessNullNotNull( @@ -1641,7 +1654,7 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, sqlUnaryExpression.OperatorType, sqlFunctionExpression.Arguments[1], typeof(bool), - sqlUnaryExpression.TypeMapping), + sqlUnaryExpression.TypeMapping)!, operandNullable); return SimplifyLogicalSqlBinaryExpression( @@ -1651,7 +1664,7 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, : ExpressionType.OrElse, left, right, - sqlUnaryExpression.TypeMapping)); + sqlUnaryExpression.TypeMapping)!); } if (!sqlFunctionExpression.IsNullable) @@ -1673,7 +1686,8 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, nullabilityPropagationElements.Add(sqlFunctionExpression.Instance); } - if (!sqlFunctionExpression.IsNiladic) + if (sqlFunctionExpression.Arguments != null + && sqlFunctionExpression.ArgumentsPropagateNullability != null) { for (var i = 0; i < sqlFunctionExpression.Arguments.Count; i++) { @@ -1695,7 +1709,7 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, sqlUnaryExpression.OperatorType, e, sqlUnaryExpression.Type, - sqlUnaryExpression.TypeMapping), + sqlUnaryExpression.TypeMapping)!, operandNullable)) .Aggregate( (r, e) => SimplifyLogicalSqlBinaryExpression( @@ -1706,13 +1720,13 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression, return result; } } - break; + break; } return sqlUnaryExpression; } - private static bool IsLogicalNot(SqlUnaryExpression sqlUnaryExpression) + private static bool IsLogicalNot(SqlUnaryExpression? sqlUnaryExpression) => sqlUnaryExpression != null && sqlUnaryExpression.OperatorType == ExpressionType.Not && sqlUnaryExpression.Type == typeof(bool); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs index e0441c8cd22..6608786f2f7 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -40,8 +42,8 @@ public SqlServerGeometryCollectionMemberTranslator([NotNull] ISqlExpressionFacto /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -53,7 +55,7 @@ public virtual SqlExpression Translate( if (Equals(member, _count)) { return _sqlExpressionFactory.Function( - instance, + instance!, "STNumGeometries", Array.Empty(), nullable: true, diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs index 178e03c40c6..ccdfee1ace4 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -45,8 +47,8 @@ public SqlServerGeometryCollectionMethodTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -55,7 +57,8 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (Equals(method, _item)) + if (Equals(method, _item) + && instance != null) { return _sqlExpressionFactory.Function( instance, @@ -70,7 +73,7 @@ public virtual SqlExpression Translate( instancePropagatesNullability: true, argumentsPropagateNullability: new[] { false }, method.ReturnType, - _typeMappingSource.FindMapping(typeof(Geometry), instance.TypeMapping.StoreType)); + _typeMappingSource.FindMapping(typeof(Geometry), instance.TypeMapping!.StoreType)); } return null; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs index 52f81fe8446..b77ab9cdb42 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -70,8 +72,8 @@ public SqlServerGeometryMemberTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -82,7 +84,7 @@ public virtual SqlExpression Translate( if (typeof(Geometry).IsAssignableFrom(member.DeclaringType)) { - Check.DebugAssert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); + Check.DebugAssert(instance!.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs index 3e349a22c06..b9f0b65edd6 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -80,8 +82,8 @@ public SqlServerGeometryMethodTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -90,7 +92,8 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (typeof(Geometry).IsAssignableFrom(method.DeclaringType)) + if (typeof(Geometry).IsAssignableFrom(method.DeclaringType) + && instance != null) { var geometryExpressions = new[] { instance }.Concat( arguments.Where(e => typeof(Geometry).IsAssignableFrom(e.Type))); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs index ecd134dd587..300ce5e7499 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -55,8 +57,8 @@ public SqlServerLineStringMemberTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -67,7 +69,7 @@ public virtual SqlExpression Translate( if (_memberToFunctionName.TryGetValue(member, out var functionName)) { - Check.DebugAssert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); + Check.DebugAssert(instance!.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var isGeography = storeType == "geography"; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs index 64fd1aa428c..a71be94de3f 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -47,8 +49,8 @@ public SqlServerLineStringMethodTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -57,7 +59,8 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (Equals(method, _getPointN)) + if (Equals(method, _getPointN) + && instance != null) { return _sqlExpressionFactory.Function( instance, @@ -72,7 +75,7 @@ public virtual SqlExpression Translate( instancePropagatesNullability: true, argumentsPropagateNullability: new[] { true }, method.ReturnType, - _typeMappingSource.FindMapping(method.ReturnType, instance.TypeMapping.StoreType)); + _typeMappingSource.FindMapping(method.ReturnType, instance.TypeMapping!.StoreType)); } return null; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs index 4e8b0584d1b..9aa41f3ddea 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -40,8 +42,8 @@ public SqlServerMultiLineStringMemberTranslator([NotNull] ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -53,7 +55,7 @@ public virtual SqlExpression Translate( if (Equals(member, _isClosed)) { return _sqlExpressionFactory.Function( - instance, + instance!, "STIsClosed", Array.Empty(), nullable: true, diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs index 6418a421ea2..9c8986a5a79 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs index 0aef5a342eb..70f66322419 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs index 04e028d6ee6..bbe9df6ef15 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { internal class SqlServerPointMemberTranslator : IMemberTranslator @@ -36,8 +38,8 @@ public SqlServerPointMemberTranslator(ISqlExpressionFactory sqlExpressionFactory _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate( - SqlExpression instance, + public SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -48,7 +50,7 @@ public SqlExpression Translate( if (typeof(Point).IsAssignableFrom(member.DeclaringType)) { - Check.DebugAssert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); + Check.DebugAssert(instance!.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs index f5cb649ace9..0bc1bac739b 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -53,8 +55,8 @@ public SqlServerPolygonMemberTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -65,7 +67,7 @@ public virtual SqlExpression Translate( if (typeof(Polygon).IsAssignableFrom(member.DeclaringType)) { - Check.DebugAssert(instance.TypeMapping != null, "Instance must have typeMapping assigned."); + Check.DebugAssert(instance!.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs index b6baf7dd91f..d39aecdf1ae 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -48,8 +50,8 @@ public SqlServerPolygonMethodTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -60,6 +62,7 @@ public virtual SqlExpression Translate( if (Equals(method, _getInteriorRingN)) { + Check.DebugAssert(instance!.TypeMapping != null, "Instance must have typeMapping assigned."); var storeType = instance.TypeMapping.StoreType; var isGeography = string.Equals(storeType, "geography", StringComparison.OrdinalIgnoreCase); diff --git a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs index c9b4046fd25..d5c51bfae8c 100644 --- a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.SqlServer.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -86,7 +88,7 @@ private SqlExpression SimplifyNegatedBinary(SqlExpression sqlExpression) : ExpressionType.Equal, sqlBinaryOperand.Left, sqlBinaryOperand.Right, - sqlBinaryOperand.TypeMapping) + sqlBinaryOperand.TypeMapping)! : sqlExpression; /// @@ -448,10 +450,10 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; var instance = (SqlExpression)Visit(sqlFunctionExpression.Instance); - SqlExpression[] arguments = default; + SqlExpression[]? arguments = default; if (!sqlFunctionExpression.IsNiladic) { - arguments = new SqlExpression[sqlFunctionExpression.Arguments.Count]; + arguments = new SqlExpression[sqlFunctionExpression.Arguments!.Count]; for (var i = 0; i < arguments.Length; i++) { arguments[i] = (SqlExpression)Visit(sqlFunctionExpression.Arguments[i]); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs index 36d9cd2c738..5b65ae9781e 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -38,8 +40,8 @@ public SqlServerByteArrayMethodTranslator([NotNull] ISqlExpressionFactory sqlExp /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs index a6c99e2248c..d3e93aaefae 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs index 5080afd0029..3f0ef0402bc 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -74,8 +76,8 @@ public SqlServerConvertTranslator([NotNull] ISqlExpressionFactory sqlExpressionF /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs index bcbb250a785..81e92b4ce33 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -79,8 +81,8 @@ public SqlServerDataLengthFunctionTranslator([NotNull] ISqlExpressionFactory sql /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -97,7 +99,7 @@ public virtual SqlExpression Translate( argument = _sqlExpressionFactory.ApplyDefaultTypeMapping(argument); } - if (_longReturningTypes.Contains(argument.TypeMapping.StoreType)) + if (_longReturningTypes.Contains(argument.TypeMapping!.StoreType)) { var result = _sqlExpressionFactory.Function( "DATALENGTH", diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs index 4d153cebdd8..33cbfbb8cb5 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -357,8 +359,8 @@ public SqlServerDateDiffFunctionsTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs index 943ccf8024d..79e82ade0d6 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -60,8 +62,8 @@ public SqlServerDateTimeMemberTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -81,7 +83,7 @@ public virtual SqlExpression Translate( { return _sqlExpressionFactory.Function( "DATEPART", - new[] { _sqlExpressionFactory.Fragment(datePart), instance }, + new[] { _sqlExpressionFactory.Fragment(datePart), instance! }, nullable: true, argumentsPropagateNullability: new[] { false, true }, returnType); @@ -92,18 +94,18 @@ public virtual SqlExpression Translate( case nameof(DateTime.Date): return _sqlExpressionFactory.Function( "CONVERT", - new[] { _sqlExpressionFactory.Fragment("date"), instance }, + new[] { _sqlExpressionFactory.Fragment("date"), instance! }, nullable: true, argumentsPropagateNullability: new[] { false, true }, returnType, declaringType == typeof(DateTime) - ? instance.TypeMapping + ? instance!.TypeMapping : _typeMappingSource.FindMapping(typeof(DateTime))); case nameof(DateTime.TimeOfDay): return _sqlExpressionFactory.Function( "CONVERT", - new[] { _sqlExpressionFactory.Fragment("time"), instance }, + new[] { _sqlExpressionFactory.Fragment("time"), instance! }, nullable: true, argumentsPropagateNullability: new[] { false, true }, returnType); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs index cf1c1755212..ee51c45cce6 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -57,8 +59,8 @@ public SqlServerDateTimeMethodTranslator([NotNull] ISqlExpressionFactory sqlExpr /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -67,7 +69,8 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (_methodInfoDatePartMapping.TryGetValue(method, out var datePart)) + if (_methodInfoDatePartMapping.TryGetValue(method, out var datePart) + && instance != null) { // DateAdd does not accept number argument outside of int range // AddYears/AddMonths take int argument so no need to check for range diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerEvaluatableExpressionFilter.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerEvaluatableExpressionFilter.cs index ac99c8d4970..e96072a166c 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerEvaluatableExpressionFilter.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerEvaluatableExpressionFilter.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs index 2aa3e481978..05481437609 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -109,8 +111,8 @@ public SqlServerFromPartsFunctionTranslator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs index fbf14ecb75d..fd088d4aa18 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.SqlServer.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -73,8 +75,8 @@ public SqlServerFullTextSearchFunctionsTranslator([NotNull] ISqlExpressionFactor /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs index 546b45c25d7..02cc75770ed 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -39,8 +41,8 @@ public SqlServerIsDateFunctionTranslator([NotNull] ISqlExpressionFactory sqlExpr /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs index 6a08804e359..e0a8d8f123e 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -89,8 +91,8 @@ public SqlServerMathTranslator([NotNull] ISqlExpressionFactory sqlExpressionFact /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMemberTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMemberTranslatorProvider.cs index d83de282ca1..cade19eb6b0 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMemberTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMemberTranslatorProvider.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs index c94e2f3a76e..f3375133dbc 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs index 0fe1a46aba7..9a0665c91aa 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -40,8 +42,8 @@ public SqlServerNewGuidTranslator([NotNull] ISqlExpressionFactory sqlExpressionF /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs index 1eeb0306f65..60035b4be6b 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -63,8 +65,8 @@ public SqlServerObjectToStringTranslator([NotNull] ISqlExpressionFactory sqlExpr /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs index 0ee8e2fc892..25f7dca4b03 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessorFactory.cs index 4ad0538f6c4..a722cebe167 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContext.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContext.cs index 3c989dd4ff7..d40ac27457d 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContext.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContext.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContextFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContextFactory.cs index befe638a606..d59d399fa13 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContextFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContextFactory.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs index 7c311dce37f..527efb37b91 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs index 4e00a89a539..9f02f6b0987 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryStringFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryStringFactory.cs index 6b6e38bc2c7..d26dec95ea6 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryStringFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryStringFactory.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs index 9e0617ca31b..c551eb6e152 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -18,8 +20,8 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerSqlTranslatingExpressionVisitor : RelationalSqlTranslatingExpressionVisitor { - private static readonly HashSet _dateTimeDataTypes - = new HashSet + private static readonly HashSet _dateTimeDataTypes + = new HashSet { "time", "date", @@ -58,13 +60,13 @@ public SqlServerSqlTranslatingExpressionVisitor( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitBinary(BinaryExpression binaryExpression) + protected override Expression? VisitBinary(BinaryExpression binaryExpression) { Check.NotNull(binaryExpression, nameof(binaryExpression)); return !(base.VisitBinary(binaryExpression) is SqlExpression visitedExpression) ? null - : (Expression)(visitedExpression is SqlBinaryExpression sqlBinary + : (Expression?)(visitedExpression is SqlBinaryExpression sqlBinary && _arithmeticOperatorTypes.Contains(sqlBinary.OperatorType) && (_dateTimeDataTypes.Contains(GetProviderType(sqlBinary.Left)) || _dateTimeDataTypes.Contains(GetProviderType(sqlBinary.Right))) @@ -78,7 +80,7 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitUnary(UnaryExpression unaryExpression) + protected override Expression? VisitUnary(UnaryExpression unaryExpression) { if (unaryExpression.NodeType == ExpressionType.ArrayLength && unaryExpression.Operand.Type == typeof(byte[])) @@ -110,7 +112,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override SqlExpression TranslateLongCount(SqlExpression sqlExpression) + public override SqlExpression? TranslateLongCount(SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -123,7 +125,7 @@ public override SqlExpression TranslateLongCount(SqlExpression sqlExpression) typeof(long))); } - private static string GetProviderType(SqlExpression expression) + private static string? GetProviderType(SqlExpression expression) => expression.TypeMapping?.StoreType; } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitorFactory.cs index db4d67b89a6..bc0bc978c29 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs index 2965df0c3a4..4ff93692397 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -38,8 +40,8 @@ public SqlServerStringMemberTranslator([NotNull] ISqlExpressionFactory sqlExpres /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index f5098665524..b0173ca83eb 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -104,8 +106,8 @@ public SqlServerStringMethodTranslator([NotNull] ISqlExpressionFactory sqlExpres /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -114,97 +116,204 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (_indexOfMethodInfo.Equals(method)) + if (instance != null) { - var argument = arguments[0]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); - argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); + if (_indexOfMethodInfo.Equals(method)) + { + var argument = arguments[0]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument)!; + argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); + + SqlExpression charIndexExpression; + var storeType = stringTypeMapping.StoreType; + if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) + || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) + { + charIndexExpression = _sqlExpressionFactory.Function( + "CHARINDEX", + new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + typeof(long)); - SqlExpression charIndexExpression; - var storeType = stringTypeMapping.StoreType; - if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) - || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) + charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); + } + else + { + charIndexExpression = _sqlExpressionFactory.Function( + "CHARINDEX", + new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + method.ReturnType); + } + + charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); + + return _sqlExpressionFactory.Case( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.Equal( + argument, + _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), + _sqlExpressionFactory.Constant(0)) + }, + charIndexExpression); + } + + if (_replaceMethodInfo.Equals(method)) { - charIndexExpression = _sqlExpressionFactory.Function( - "CHARINDEX", - new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, + var firstArgument = arguments[0]; + var secondArgument = arguments[1]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); + + instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); + firstArgument = _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping); + secondArgument = _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping); + + return _sqlExpressionFactory.Function( + "REPLACE", + new[] { instance, firstArgument, secondArgument }, nullable: true, - argumentsPropagateNullability: new[] { true, true }, - typeof(long)); + argumentsPropagateNullability: new[] { true, true, true }, + method.ReturnType, + stringTypeMapping); + } - charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); + if (_toLowerMethodInfo.Equals(method) + || _toUpperMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER", + new[] { instance }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + method.ReturnType, + instance.TypeMapping); } - else + + if (_substringMethodInfo.Equals(method)) { - charIndexExpression = _sqlExpressionFactory.Function( - "CHARINDEX", - new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, + return _sqlExpressionFactory.Function( + "SUBSTRING", + new[] + { + instance, + _sqlExpressionFactory.Add( + arguments[0], + _sqlExpressionFactory.Constant(1)), + arguments[1] + }, nullable: true, - argumentsPropagateNullability: new[] { true, true }, - method.ReturnType); + argumentsPropagateNullability: new[] { true, true, true }, + method.ReturnType, + instance.TypeMapping); } - charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); + if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true + || (_trimStartMethodInfoWithCharArrayArg.Equals(method) + // SqlServer LTRIM does not take arguments + && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) + { + return _sqlExpressionFactory.Function( + "LTRIM", + new[] { instance }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + instance.Type, + instance.TypeMapping); + } - return _sqlExpressionFactory.Case( - new[] - { - new CaseWhenClause( - _sqlExpressionFactory.Equal( - argument, - _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), - _sqlExpressionFactory.Constant(0)) - }, - charIndexExpression); - } + if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true + || (_trimEndMethodInfoWithCharArrayArg.Equals(method) + // SqlServer RTRIM does not take arguments + && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) + { + return _sqlExpressionFactory.Function( + "RTRIM", + new[] { instance }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + instance.Type, + instance.TypeMapping); + } - if (_replaceMethodInfo.Equals(method)) - { - var firstArgument = arguments[0]; - var secondArgument = arguments[1]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); + if (_trimMethodInfoWithoutArgs?.Equals(method) == true + || (_trimMethodInfoWithCharArrayArg.Equals(method) + // SqlServer LTRIM/RTRIM does not take arguments + && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) + { + return _sqlExpressionFactory.Function( + "LTRIM", + new[] + { + _sqlExpressionFactory.Function( + "RTRIM", + new[] { instance }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + instance.Type, + instance.TypeMapping) + }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + instance.Type, + instance.TypeMapping); + } - instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); - firstArgument = _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping); - secondArgument = _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping); + if (_containsMethodInfo.Equals(method)) + { + var pattern = arguments[0]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); + instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); + pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); - return _sqlExpressionFactory.Function( - "REPLACE", - new[] { instance, firstArgument, secondArgument }, - nullable: true, - argumentsPropagateNullability: new[] { true, true, true }, - method.ReturnType, - stringTypeMapping); - } + if (pattern is SqlConstantExpression constantPattern) + { + if (!(constantPattern.Value is string patternValue)) + { + return _sqlExpressionFactory.Like( + instance, + _sqlExpressionFactory.Constant(null, stringTypeMapping)); + } - if (_toLowerMethodInfo.Equals(method) - || _toUpperMethodInfo.Equals(method)) - { - return _sqlExpressionFactory.Function( - _toLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER", - new[] { instance }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - method.ReturnType, - instance.TypeMapping); - } + if (patternValue.Length == 0) + { + return _sqlExpressionFactory.Constant(true); + } + + return patternValue.Any(IsLikeWildChar) + ? _sqlExpressionFactory.Like( + instance, + _sqlExpressionFactory.Constant($"%{EscapeLikePattern(patternValue)}%"), + _sqlExpressionFactory.Constant(LikeEscapeString)) + : _sqlExpressionFactory.Like(instance, _sqlExpressionFactory.Constant($"%{patternValue}%")); + } - if (_substringMethodInfo.Equals(method)) - { - return _sqlExpressionFactory.Function( - "SUBSTRING", - new[] - { - instance, - _sqlExpressionFactory.Add( - arguments[0], - _sqlExpressionFactory.Constant(1)), - arguments[1] - }, - nullable: true, - argumentsPropagateNullability: new[] { true, true, true }, - method.ReturnType, - instance.TypeMapping); + return _sqlExpressionFactory.OrElse( + _sqlExpressionFactory.Like( + pattern, + _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), + _sqlExpressionFactory.GreaterThan( + _sqlExpressionFactory.Function( + "CHARINDEX", + new[] { pattern, instance }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + typeof(int)), + _sqlExpressionFactory.Constant(0))); + } + + if (_startsWithMethodInfo.Equals(method)) + { + return TranslateStartsEndsWith(instance, arguments[0], true); + } + + if (_endsWithMethodInfo.Equals(method)) + { + return TranslateStartsEndsWith(instance, arguments[0], false); + } } if (_isNullOrEmptyMethodInfo.Equals(method)) @@ -229,100 +338,6 @@ public virtual SqlExpression Translate( _sqlExpressionFactory.Constant(string.Empty, argument.TypeMapping))); } - if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true - || (_trimStartMethodInfoWithCharArrayArg.Equals(method) - // SqlServer LTRIM does not take arguments - && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) - { - return _sqlExpressionFactory.Function( - "LTRIM", - new[] { instance }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - instance.Type, - instance.TypeMapping); - } - - if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true - || (_trimEndMethodInfoWithCharArrayArg.Equals(method) - // SqlServer RTRIM does not take arguments - && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) - { - return _sqlExpressionFactory.Function( - "RTRIM", - new[] { instance }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - instance.Type, - instance.TypeMapping); - } - - if (_trimMethodInfoWithoutArgs?.Equals(method) == true - || (_trimMethodInfoWithCharArrayArg.Equals(method) - // SqlServer LTRIM/RTRIM does not take arguments - && ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) - { - return _sqlExpressionFactory.Function( - "LTRIM", - new[] - { - _sqlExpressionFactory.Function( - "RTRIM", - new[] { instance }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - instance.Type, - instance.TypeMapping) - }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - instance.Type, - instance.TypeMapping); - } - - if (_containsMethodInfo.Equals(method)) - { - var pattern = arguments[0]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); - instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); - pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); - - if (pattern is SqlConstantExpression constantPattern) - { - if (!(constantPattern.Value is string patternValue)) - { - return _sqlExpressionFactory.Like( - instance, - _sqlExpressionFactory.Constant(null, stringTypeMapping)); - } - - if (patternValue.Length == 0) - { - return _sqlExpressionFactory.Constant(true); - } - - return patternValue.Any(IsLikeWildChar) - ? _sqlExpressionFactory.Like( - instance, - _sqlExpressionFactory.Constant($"%{EscapeLikePattern(patternValue)}%"), - _sqlExpressionFactory.Constant(LikeEscapeString)) - : _sqlExpressionFactory.Like(instance, _sqlExpressionFactory.Constant($"%{patternValue}%")); - } - - return _sqlExpressionFactory.OrElse( - _sqlExpressionFactory.Like( - pattern, - _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), - _sqlExpressionFactory.GreaterThan( - _sqlExpressionFactory.Function( - "CHARINDEX", - new[] { pattern, instance }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - typeof(int)), - _sqlExpressionFactory.Constant(0))); - } - if (_firstOrDefaultMethodInfoWithoutArgs.Equals(method)) { var argument = arguments[0]; @@ -355,16 +370,6 @@ public virtual SqlExpression Translate( method.ReturnType); } - if (_startsWithMethodInfo.Equals(method)) - { - return TranslateStartsEndsWith(instance, arguments[0], true); - } - - if (_endsWithMethodInfo.Equals(method)) - { - return TranslateStartsEndsWith(instance, arguments[0], false); - } - return null; } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs index 85d644ab24a..1a4ca1d1b04 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// @@ -47,8 +49,8 @@ public SqlServerTimeSpanMemberTranslator([NotNull] ISqlExpressionFactory sqlExpr /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -60,7 +62,7 @@ public virtual SqlExpression Translate( if (member.DeclaringType == typeof(TimeSpan) && _datePartMappings.TryGetValue(member.Name, out string value)) { return _sqlExpressionFactory.Function( - "DATEPART", new[] { _sqlExpressionFactory.Fragment(value), instance }, + "DATEPART", new[] { _sqlExpressionFactory.Fragment(value), instance! }, nullable: true, argumentsPropagateNullability: new[] { false, true }, returnType); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs index 4674327e238..eb42f8cbdb9 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -38,8 +40,8 @@ public SqliteByteArrayMethodTranslator([NotNull] ISqlExpressionFactory sqlExpres /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs index 42947807fef..f96bee31277 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -55,8 +57,8 @@ public SqliteDateTimeAddTranslator([NotNull] ISqlExpressionFactory sqlExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -65,7 +67,7 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - SqlExpression modifier = null; + SqlExpression? modifier = null; if (_addMilliseconds.Equals(method)) { modifier = _sqlExpressionFactory.Add( @@ -107,7 +109,7 @@ public virtual SqlExpression Translate( _sqlExpressionFactory, method.ReturnType, "%Y-%m-%d %H:%M:%f", - instance, + instance!, new[] { modifier }), _sqlExpressionFactory.Constant("0") }, diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs index 57c1a8152ba..1e058dac7ee 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -52,8 +54,8 @@ public SqliteDateTimeMemberTranslator([NotNull] ISqlExpressionFactory sqlExpress /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -73,7 +75,7 @@ public virtual SqlExpression Translate( _sqlExpressionFactory, typeof(string), datePart, - instance), + instance!), returnType); } @@ -84,7 +86,7 @@ public virtual SqlExpression Translate( _sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "julianday", - new[] { instance }, + new[] { instance! }, nullable: true, argumentsPropagateNullability: new[] { true }, typeof(double)), @@ -102,7 +104,7 @@ public virtual SqlExpression Translate( _sqlExpressionFactory, typeof(string), "%f", - instance), + instance!), typeof(double)), _sqlExpressionFactory.Constant(1000)), _sqlExpressionFactory.Constant(1000)); @@ -124,7 +126,7 @@ public virtual SqlExpression Translate( break; case nameof(DateTime.Date): - timestring = instance; + timestring = instance!; modifiers.Add(_sqlExpressionFactory.Constant("start of day")); break; @@ -136,7 +138,7 @@ public virtual SqlExpression Translate( case nameof(DateTime.TimeOfDay): format = "%H:%M:%f"; - timestring = instance; + timestring = instance!; break; default: diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs index 71eb318e9d5..00d0dea8e73 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -30,21 +32,21 @@ public static SqlFunctionExpression Strftime( [NotNull] Type returnType, [NotNull] string format, [NotNull] SqlExpression timestring, - [CanBeNull] IEnumerable modifiers = null, - [CanBeNull] RelationalTypeMapping typeMapping = null) + [CanBeNull] IEnumerable? modifiers = null, + [CanBeNull] RelationalTypeMapping? typeMapping = null) { modifiers ??= Enumerable.Empty(); // If the inner call is another strftime then shortcut a double call if (timestring is SqlFunctionExpression rtrimFunction && rtrimFunction.Name == "rtrim" - && rtrimFunction.Arguments.Count == 2 + && rtrimFunction.Arguments!.Count == 2 && rtrimFunction.Arguments[0] is SqlFunctionExpression rtrimFunction2 && rtrimFunction2.Name == "rtrim" - && rtrimFunction2.Arguments.Count == 2 + && rtrimFunction2.Arguments!.Count == 2 && rtrimFunction2.Arguments[0] is SqlFunctionExpression strftimeFunction && strftimeFunction.Name == "strftime" - && strftimeFunction.Arguments.Count > 1) + && strftimeFunction.Arguments!.Count > 1) { // Use its timestring parameter directly in place of ours timestring = strftimeFunction.Arguments[1]; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs index 4af5643736a..b3499545888 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -71,8 +73,8 @@ public SqliteMathTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -83,11 +85,11 @@ public virtual SqlExpression Translate( if (_supportedMethods.TryGetValue(method, out var sqlFunctionName)) { - RelationalTypeMapping typeMapping; - List newArguments = null; + RelationalTypeMapping? typeMapping; + List? newArguments = null; if (sqlFunctionName == "max" || sqlFunctionName == "max") { - typeMapping = ExpressionExtensions.InferTypeMapping(arguments[0], arguments[1]); + typeMapping = ExpressionExtensions.InferTypeMapping(arguments![0]!, arguments[1]!); newArguments = new List { _sqlExpressionFactory.ApplyTypeMapping(arguments[0], typeMapping), diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs index c156bf44752..85b78339d1c 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs index 97085baae59..e5f6c32c7de 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteObjectToStringTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteObjectToStringTranslator.cs index b3be57b267b..39c202b43dd 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteObjectToStringTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteObjectToStringTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -58,8 +60,8 @@ public SqliteObjectToStringTranslator([NotNull] ISqlExpressionFactory sqlExpress /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs index a648833e5be..0863d4fa30d 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs @@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -62,7 +64,7 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression) Visit( selectExpression.Limit - ?? new SqlConstantExpression(Expression.Constant(-1), selectExpression.Offset.TypeMapping)); + ?? new SqlConstantExpression(Expression.Constant(-1), selectExpression.Offset!.TypeMapping)); if (selectExpression.Offset != null) { diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs index 37ff3cc5589..dd36f159aa1 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryStringFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryStringFactory.cs index 45a8cf8f44c..8964d5ba082 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryStringFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryStringFactory.cs @@ -8,6 +8,8 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessor.cs index 5c829152581..f604da8e350 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessor.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Sqlite.Internal; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessorFactory.cs index a457df1e53d..2957ff4bb28 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryTranslationPostprocessorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs index c16e581ed3a..1b06a6b2014 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Sqlite.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -62,7 +64,7 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateOrderBy( + protected override ShapedQueryExpression? TranslateOrderBy( ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) @@ -96,7 +98,7 @@ protected override ShapedQueryExpression TranslateOrderBy( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) + protected override ShapedQueryExpression? TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { Check.NotNull(source, nameof(source)); Check.NotNull(keySelector, nameof(keySelector)); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs index b4251786bf2..e516e5da6fd 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs index 0f76383b93a..70335729590 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -45,8 +47,8 @@ public SqliteRegexMethodTranslator([NotNull] ISqlExpressionFactory sqlExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs index cabf974bdf7..b7b48a1b881 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Sqlite.Internal; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -93,7 +95,7 @@ public SqliteSqlTranslatingExpressionVisitor( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitUnary(UnaryExpression unaryExpression) + protected override Expression? VisitUnary(UnaryExpression unaryExpression) { Check.NotNull(unaryExpression, nameof(unaryExpression)); @@ -145,7 +147,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected override Expression VisitBinary(BinaryExpression binaryExpression) + protected override Expression? VisitBinary(BinaryExpression binaryExpression) { Check.NotNull(binaryExpression, nameof(binaryExpression)); @@ -196,7 +198,7 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override SqlExpression TranslateAverage(SqlExpression sqlExpression) + public override SqlExpression? TranslateAverage(SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -217,7 +219,7 @@ public override SqlExpression TranslateAverage(SqlExpression sqlExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override SqlExpression TranslateMax(SqlExpression sqlExpression) + public override SqlExpression? TranslateMax(SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -241,13 +243,7 @@ public override SqlExpression TranslateMax(SqlExpression sqlExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override SqlExpression TranslateMin(SqlExpression sqlExpression) + public override SqlExpression? TranslateMin(SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -271,7 +267,7 @@ public override SqlExpression TranslateMin(SqlExpression sqlExpression) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override SqlExpression TranslateSum(SqlExpression sqlExpression) + public override SqlExpression? TranslateSum(SqlExpression sqlExpression) { Check.NotNull(sqlExpression, nameof(sqlExpression)); @@ -286,7 +282,7 @@ public override SqlExpression TranslateSum(SqlExpression sqlExpression) return visitedExpression; } - private static Type GetProviderType(SqlExpression expression) + private static Type? GetProviderType(SqlExpression? expression) => expression == null ? null : expression.TypeMapping?.Converter?.ProviderClrType diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitorFactory.cs index c314d1b570d..6dff809a824 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitorFactory.cs @@ -4,6 +4,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringLengthTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringLengthTranslator.cs index b8a2e1022cc..78a5b049561 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringLengthTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringLengthTranslator.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -38,8 +40,8 @@ public SqliteStringLengthTranslator([NotNull] ISqlExpressionFactory sqlExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs index 45aaff051a6..f2008e6f3d6 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -108,8 +110,8 @@ public SqliteStringMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressio /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -118,66 +120,122 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (_indexOfMethodInfo.Equals(method)) + if (instance != null) { - var argument = arguments[0]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); + if (_indexOfMethodInfo.Equals(method)) + { + var argument = arguments[0]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); - return _sqlExpressionFactory.Subtract( - _sqlExpressionFactory.Function( - "instr", + return _sqlExpressionFactory.Subtract( + _sqlExpressionFactory.Function( + "instr", + new[] + { + _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), + _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping) + }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + method.ReturnType), + _sqlExpressionFactory.Constant(1)); + } + + if (_replaceMethodInfo.Equals(method)) + { + var firstArgument = arguments[0]; + var secondArgument = arguments[1]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); + + return _sqlExpressionFactory.Function( + "replace", new[] { - _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), - _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping) + _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), + _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping), + _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping) }, nullable: true, - argumentsPropagateNullability: new[] { true, true }, - method.ReturnType), - _sqlExpressionFactory.Constant(1)); - } + argumentsPropagateNullability: new[] { true, true, true }, + method.ReturnType, + stringTypeMapping); + } - if (_replaceMethodInfo.Equals(method)) - { - var firstArgument = arguments[0]; - var secondArgument = arguments[1]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); + if (_toLowerMethodInfo.Equals(method) + || _toUpperMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + _toLowerMethodInfo.Equals(method) ? "lower" : "upper", + new[] { instance }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + method.ReturnType, + instance.TypeMapping); + } - return _sqlExpressionFactory.Function( - "replace", - new[] - { - _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), - _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping), - _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping) - }, - nullable: true, - argumentsPropagateNullability: new[] { true, true, true }, - method.ReturnType, - stringTypeMapping); - } + if (_substringMethodInfo.Equals(method)) + { + return _sqlExpressionFactory.Function( + "substr", + new[] { instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] }, + nullable: true, + argumentsPropagateNullability: new[] { true, true, true }, + method.ReturnType, + instance.TypeMapping); + } - if (_toLowerMethodInfo.Equals(method) - || _toUpperMethodInfo.Equals(method)) - { - return _sqlExpressionFactory.Function( - _toLowerMethodInfo.Equals(method) ? "lower" : "upper", - new[] { instance }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - method.ReturnType, - instance.TypeMapping); - } + if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true + || _trimStartMethodInfoWithCharArg?.Equals(method) == true + || _trimStartMethodInfoWithCharArrayArg.Equals(method)) + { + return ProcessTrimMethod(instance, arguments, "ltrim"); + } - if (_substringMethodInfo.Equals(method)) - { - return _sqlExpressionFactory.Function( - "substr", - new[] { instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] }, - nullable: true, - argumentsPropagateNullability: new[] { true, true, true }, - method.ReturnType, - instance.TypeMapping); + if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true + || _trimEndMethodInfoWithCharArg?.Equals(method) == true + || _trimEndMethodInfoWithCharArrayArg.Equals(method)) + { + return ProcessTrimMethod(instance, arguments, "rtrim"); + } + + if (_trimMethodInfoWithoutArgs?.Equals(method) == true + || _trimMethodInfoWithCharArg?.Equals(method) == true + || _trimMethodInfoWithCharArrayArg.Equals(method)) + { + return ProcessTrimMethod(instance, arguments, "trim"); + } + + if (_containsMethodInfo.Equals(method)) + { + var pattern = arguments[0]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); + + instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); + pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); + + return _sqlExpressionFactory.OrElse( + _sqlExpressionFactory.Equal( + pattern, + _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), + _sqlExpressionFactory.GreaterThan( + _sqlExpressionFactory.Function( + "instr", + new[] { instance, pattern }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + typeof(int)), + _sqlExpressionFactory.Constant(0))); + } + + if (_startsWithMethodInfo.Equals(method)) + { + return TranslateStartsEndsWith(instance, arguments[0], true); + } + + if (_endsWithMethodInfo.Equals(method)) + { + return TranslateStartsEndsWith(instance, arguments[0], false); + } } if (_isNullOrWhiteSpaceMethodInfo.Equals(method)) @@ -197,49 +255,6 @@ public virtual SqlExpression Translate( _sqlExpressionFactory.Constant(string.Empty))); } - if (_trimStartMethodInfoWithoutArgs?.Equals(method) == true - || _trimStartMethodInfoWithCharArg?.Equals(method) == true - || _trimStartMethodInfoWithCharArrayArg.Equals(method)) - { - return ProcessTrimMethod(instance, arguments, "ltrim"); - } - - if (_trimEndMethodInfoWithoutArgs?.Equals(method) == true - || _trimEndMethodInfoWithCharArg?.Equals(method) == true - || _trimEndMethodInfoWithCharArrayArg.Equals(method)) - { - return ProcessTrimMethod(instance, arguments, "rtrim"); - } - - if (_trimMethodInfoWithoutArgs?.Equals(method) == true - || _trimMethodInfoWithCharArg?.Equals(method) == true - || _trimMethodInfoWithCharArrayArg.Equals(method)) - { - return ProcessTrimMethod(instance, arguments, "trim"); - } - - if (_containsMethodInfo.Equals(method)) - { - var pattern = arguments[0]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); - - instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); - pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping); - - return _sqlExpressionFactory.OrElse( - _sqlExpressionFactory.Equal( - pattern, - _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), - _sqlExpressionFactory.GreaterThan( - _sqlExpressionFactory.Function( - "instr", - new[] { instance, pattern }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - typeof(int)), - _sqlExpressionFactory.Constant(0))); - } - if (_firstOrDefaultMethodInfoWithoutArgs.Equals(method)) { var argument = arguments[0]; @@ -272,16 +287,6 @@ public virtual SqlExpression Translate( method.ReturnType); } - if (_startsWithMethodInfo.Equals(method)) - { - return TranslateStartsEndsWith(instance, arguments[0], true); - } - - if (_endsWithMethodInfo.Equals(method)) - { - return TranslateStartsEndsWith(instance, arguments[0], false); - } - return null; } @@ -403,7 +408,7 @@ private string EscapeLikePattern(string pattern) return builder.ToString(); } - private SqlExpression ProcessTrimMethod(SqlExpression instance, IReadOnlyList arguments, string functionName) + private SqlExpression? ProcessTrimMethod(SqlExpression instance, IReadOnlyList arguments, string functionName) { var typeMapping = instance.TypeMapping; if (typeMapping == null) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs index f1364b48d51..3e6dbe39fef 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -40,8 +42,8 @@ public SqliteGeometryCollectionMemberTranslator([NotNull] ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -53,7 +55,7 @@ public virtual SqlExpression Translate( return Equals(member, _count) ? _sqlExpressionFactory.Function( "NumGeometries", - new[] { instance }, + new[] { instance! }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs index a681f67e716..0e1e0ae2217 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -40,8 +42,8 @@ public SqliteGeometryCollectionMethodTranslator([NotNull] ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -56,7 +58,7 @@ public virtual SqlExpression Translate( "GeometryN", new[] { - instance, + instance!, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs index a452b610879..e6c226e7fea 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -60,8 +62,8 @@ public SqliteGeometryMemberTranslator([NotNull] ISqlExpressionFactory sqlExpress /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -70,12 +72,14 @@ public virtual SqlExpression Translate( Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); - if (_memberToFunctionName.TryGetValue(member, out var functionName)) + if (instance != null) { - return returnType == typeof(bool) - ? _sqlExpressionFactory.Case( - new[] - { + if (_memberToFunctionName.TryGetValue(member, out var functionName)) + { + return returnType == typeof(bool) + ? _sqlExpressionFactory.Case( + new[] + { new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( @@ -84,23 +88,23 @@ public virtual SqlExpression Translate( nullable: false, argumentsPropagateNullability: new[] { false }, returnType)) - }, - null) - : (SqlExpression)_sqlExpressionFactory.Function( - functionName, - new[] { instance }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - returnType); - } + }, + null) + : (SqlExpression)_sqlExpressionFactory.Function( + functionName, + new[] { instance }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + returnType); + } - if (Equals(member, _geometryType)) - { - return _sqlExpressionFactory.Case( - _sqlExpressionFactory.Function( - "rtrim", - new SqlExpression[] - { + if (Equals(member, _geometryType)) + { + return _sqlExpressionFactory.Case( + _sqlExpressionFactory.Function( + "rtrim", + new SqlExpression[] + { _sqlExpressionFactory.Function( "GeometryType", new[] { instance }, @@ -108,32 +112,32 @@ public virtual SqlExpression Translate( argumentsPropagateNullability: new[] { true }, returnType), _sqlExpressionFactory.Constant(" ZM") + }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + returnType), + new[] + { + new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant("Point")), + new CaseWhenClause(_sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant("LineString")), + new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant("Polygon")), + new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant("MultiPoint")), + new CaseWhenClause( + _sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant("MultiLineString")), + new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant("MultiPolygon")), + new CaseWhenClause( + _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant("GeometryCollection")) }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - returnType), - new[] - { - new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant("Point")), - new CaseWhenClause(_sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant("LineString")), - new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant("Polygon")), - new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant("MultiPoint")), - new CaseWhenClause( - _sqlExpressionFactory.Constant("MULTILINESTRING"), _sqlExpressionFactory.Constant("MultiLineString")), - new CaseWhenClause(_sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant("MultiPolygon")), - new CaseWhenClause( - _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant("GeometryCollection")) - }, - null); - } + null); + } - if (Equals(member, _ogcGeometryType)) - { - return _sqlExpressionFactory.Case( - _sqlExpressionFactory.Function( - "rtrim", - new SqlExpression[] - { + if (Equals(member, _ogcGeometryType)) + { + return _sqlExpressionFactory.Case( + _sqlExpressionFactory.Function( + "rtrim", + new SqlExpression[] + { _sqlExpressionFactory.Function( "GeometryType", new[] { instance }, @@ -141,29 +145,30 @@ public virtual SqlExpression Translate( argumentsPropagateNullability: new[] { true }, typeof(string)), _sqlExpressionFactory.Constant(" ZM") + }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + typeof(string)), + new[] + { + new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant(OgcGeometryType.Point)), + new CaseWhenClause( + _sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant(OgcGeometryType.LineString)), + new CaseWhenClause( + _sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.Polygon)), + new CaseWhenClause( + _sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPoint)), + new CaseWhenClause( + _sqlExpressionFactory.Constant("MULTILINESTRING"), + _sqlExpressionFactory.Constant(OgcGeometryType.MultiLineString)), + new CaseWhenClause( + _sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPolygon)), + new CaseWhenClause( + _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), + _sqlExpressionFactory.Constant(OgcGeometryType.GeometryCollection)) }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - typeof(string)), - new[] - { - new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant(OgcGeometryType.Point)), - new CaseWhenClause( - _sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant(OgcGeometryType.LineString)), - new CaseWhenClause( - _sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.Polygon)), - new CaseWhenClause( - _sqlExpressionFactory.Constant("MULTIPOINT"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPoint)), - new CaseWhenClause( - _sqlExpressionFactory.Constant("MULTILINESTRING"), - _sqlExpressionFactory.Constant(OgcGeometryType.MultiLineString)), - new CaseWhenClause( - _sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant(OgcGeometryType.MultiPolygon)), - new CaseWhenClause( - _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), - _sqlExpressionFactory.Constant(OgcGeometryType.GeometryCollection)) - }, - null); + null); + } } return null; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs index 32e0f2cb3d1..85812dc7eb2 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs @@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -76,8 +78,8 @@ public SqliteGeometryMethodTranslator([NotNull] ISqlExpressionFactory sqlExpress /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -86,23 +88,25 @@ public virtual SqlExpression Translate( Check.NotNull(arguments, nameof(arguments)); Check.NotNull(logger, nameof(logger)); - if (_methodToFunctionName.TryGetValue(method, out var functionName)) + if (instance != null) { - var finalArguments = new[] { instance }.Concat(arguments); - - if (method.ReturnType == typeof(bool)) + if (_methodToFunctionName.TryGetValue(method, out var functionName)) { - var nullCheck = (SqlExpression)_sqlExpressionFactory.IsNotNull(instance); - foreach (var argument in arguments) - { - nullCheck = _sqlExpressionFactory.AndAlso( - nullCheck, - _sqlExpressionFactory.IsNotNull(argument)); - } + var finalArguments = new[] { instance }.Concat(arguments); - return _sqlExpressionFactory.Case( - new[] + if (method.ReturnType == typeof(bool)) + { + var nullCheck = (SqlExpression)_sqlExpressionFactory.IsNotNull(instance); + foreach (var argument in arguments) { + nullCheck = _sqlExpressionFactory.AndAlso( + nullCheck, + _sqlExpressionFactory.IsNotNull(argument)); + } + + return _sqlExpressionFactory.Case( + new[] + { new CaseWhenClause( nullCheck, _sqlExpressionFactory.Function( @@ -111,44 +115,45 @@ public virtual SqlExpression Translate( nullable: false, finalArguments.Select(a => false), method.ReturnType)) - }, - null); - } + }, + null); + } - return _sqlExpressionFactory.Function( - functionName, - finalArguments, - nullable: true, - finalArguments.Select(a => true), - method.ReturnType); - } + return _sqlExpressionFactory.Function( + functionName, + finalArguments, + nullable: true, + finalArguments.Select(a => true), + method.ReturnType); + } - if (Equals(method, _getGeometryN)) - { - return _sqlExpressionFactory.Function( - "GeometryN", - new[] - { + if (Equals(method, _getGeometryN)) + { + return _sqlExpressionFactory.Function( + "GeometryN", + new[] + { instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) - }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - method.ReturnType); - } - - if (Equals(method, _isWithinDistance)) - { - return _sqlExpressionFactory.LessThanOrEqual( - _sqlExpressionFactory.Function( - "Distance", - new[] { instance, arguments[0] }, + }, nullable: true, argumentsPropagateNullability: new[] { true, true }, - typeof(double)), - arguments[1]); + method.ReturnType); + } + + if (Equals(method, _isWithinDistance)) + { + return _sqlExpressionFactory.LessThanOrEqual( + _sqlExpressionFactory.Function( + "Distance", + new[] { instance, arguments[0] }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + typeof(double)), + arguments[1]); + } } return null; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs index d93ba9e3a85..e7bea4ecdc6 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -50,8 +52,8 @@ public SqliteLineStringMemberTranslator([NotNull] ISqlExpressionFactory sqlExpre /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -60,7 +62,8 @@ public virtual SqlExpression Translate( Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); - if (_memberToFunctionName.TryGetValue(member, out var functionName)) + if (_memberToFunctionName.TryGetValue(member, out var functionName) + && instance != null) { return returnType == typeof(bool) ? _sqlExpressionFactory.Case( diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs index c71296e6f89..ffbd0c129d7 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -42,8 +44,8 @@ public SqliteLineStringMethodTranslator([NotNull] ISqlExpressionFactory sqlExpre /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -58,7 +60,7 @@ public virtual SqlExpression Translate( "PointN", new[] { - instance, + instance!, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs index 2002388cb8a..2dbdb9fbc48 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -40,8 +42,8 @@ public SqliteMultiLineStringMemberTranslator([NotNull] ISqlExpressionFactory sql /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -50,7 +52,8 @@ public virtual SqlExpression Translate( Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); - if (Equals(member, _isClosed)) + if (Equals(member, _isClosed) + && instance != null) { return _sqlExpressionFactory.Case( new[] diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs index d5db14afea3..83d215852fa 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs index 0c706b434c2..78774a36078 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs index ff25e3f055d..17738940ebf 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -48,8 +50,8 @@ public SqlitePointMemberTranslator([NotNull] ISqlExpressionFactory sqlExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -61,7 +63,7 @@ public virtual SqlExpression Translate( return _memberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function( functionName, - new[] { instance }, + new[] { instance! }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs index 3efb66baf23..9f78b3cd970 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs @@ -11,6 +11,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -47,8 +49,8 @@ public SqlitePolygonMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressi /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MemberInfo member, Type returnType, IDiagnosticsLogger logger) @@ -60,7 +62,7 @@ public virtual SqlExpression Translate( return _memberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function( functionName, - new[] { instance }, + new[] { instance! }, nullable: true, argumentsPropagateNullability: new[] { true }, returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs index 16ba3050daf..ad9ec68a0d9 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs @@ -10,6 +10,8 @@ using Microsoft.EntityFrameworkCore.Utilities; using NetTopologySuite.Geometries; +#nullable enable + namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// @@ -42,8 +44,8 @@ public SqlitePolygonMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressi /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate( - SqlExpression instance, + public virtual SqlExpression? Translate( + SqlExpression? instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) @@ -56,7 +58,7 @@ public virtual SqlExpression Translate( { return _sqlExpressionFactory.Function( "InteriorRingN", - new[] { instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)) }, + new[] { instance!, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)) }, nullable: true, argumentsPropagateNullability: new[] { true, true }, method.ReturnType); diff --git a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs index 12c82aabae7..de17d177875 100644 --- a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs @@ -85,7 +85,7 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) protected virtual QueryCompilationContext QueryCompilationContext { get; } /// - protected override Expression VisitExtension(Expression extensionExpression) + protected override Expression? VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); @@ -102,7 +102,7 @@ protected override Expression VisitExtension(Expression extensionExpression) { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); - ShapedQueryExpression CheckTranslated(ShapedQueryExpression translated) + ShapedQueryExpression CheckTranslated(ShapedQueryExpression? translated) { return translated ?? throw new InvalidOperationException( @@ -658,14 +658,14 @@ private static Expression AccessInnerTransparentField( /// The clr type of the entity type to look for. /// A shaped query expression for the given clr type. [Obsolete("Use overload which takes IEntityType.")] - protected abstract ShapedQueryExpression CreateShapedQueryExpression([NotNull] Type elementType); + protected abstract ShapedQueryExpression? CreateShapedQueryExpression([NotNull] Type elementType); /// /// Creates a for the given entity type. /// /// The the entity type. /// A shaped query expression for the given entity type. - protected abstract ShapedQueryExpression CreateShapedQueryExpression([NotNull] IEntityType entityType); + protected abstract ShapedQueryExpression? CreateShapedQueryExpression([NotNull] IEntityType entityType); /// /// Translates method over the given source. @@ -673,7 +673,7 @@ private static Expression AccessInnerTransparentField( /// The shaped query on which the operator is applied. /// The predicate supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateAll([NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); + protected abstract ShapedQueryExpression? TranslateAll([NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); /// /// Translates method and other overloads over the given source. @@ -681,7 +681,7 @@ private static Expression AccessInnerTransparentField( /// The shaped query on which the operator is applied. /// The predicate supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateAny( + protected abstract ShapedQueryExpression? TranslateAny( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? predicate); @@ -692,7 +692,7 @@ protected abstract ShapedQueryExpression TranslateAny( /// The selector supplied in the call. /// The result type after the operation. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateAverage( + protected abstract ShapedQueryExpression? TranslateAverage( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? selector, [NotNull] Type resultType); @@ -703,7 +703,7 @@ protected abstract ShapedQueryExpression TranslateAverage( /// The shaped query on which the operator is applied. /// The type result is being casted to. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateCast([NotNull] ShapedQueryExpression source, [NotNull] Type castType); + protected abstract ShapedQueryExpression? TranslateCast([NotNull] ShapedQueryExpression source, [NotNull] Type castType); /// /// Translates method over the given source. @@ -711,7 +711,7 @@ protected abstract ShapedQueryExpression TranslateAverage( /// The shaped query on which the operator is applied. /// The other source to perform concat. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateConcat( + protected abstract ShapedQueryExpression? TranslateConcat( [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); @@ -721,7 +721,7 @@ protected abstract ShapedQueryExpression TranslateConcat( /// The shaped query on which the operator is applied. /// The item to search for. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateContains([NotNull] ShapedQueryExpression source, [NotNull] Expression item); + protected abstract ShapedQueryExpression? TranslateContains([NotNull] ShapedQueryExpression source, [NotNull] Expression item); /// /// Translates method and other overloads over the given source. @@ -729,7 +729,7 @@ protected abstract ShapedQueryExpression TranslateConcat( /// The shaped query on which the operator is applied. /// The predicate supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateCount( + protected abstract ShapedQueryExpression? TranslateCount( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? predicate); @@ -739,7 +739,7 @@ protected abstract ShapedQueryExpression TranslateCount( /// The shaped query on which the operator is applied. /// The default value to use. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateDefaultIfEmpty( + protected abstract ShapedQueryExpression? TranslateDefaultIfEmpty( [NotNull] ShapedQueryExpression source, [CanBeNull] Expression? defaultValue); @@ -748,7 +748,7 @@ protected abstract ShapedQueryExpression TranslateDefaultIfEmpty( /// /// The shaped query on which the operator is applied. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateDistinct([NotNull] ShapedQueryExpression source); + protected abstract ShapedQueryExpression? TranslateDistinct([NotNull] ShapedQueryExpression source); /// /// Translates method or @@ -758,7 +758,7 @@ protected abstract ShapedQueryExpression TranslateDefaultIfEmpty( /// The index of the element. /// A value indicating whether default should be returned or throw. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateElementAtOrDefault( + protected abstract ShapedQueryExpression? TranslateElementAtOrDefault( [NotNull] ShapedQueryExpression source, [NotNull] Expression index, bool returnDefault); @@ -769,7 +769,7 @@ protected abstract ShapedQueryExpression TranslateElementAtOrDefault( /// The shaped query on which the operator is applied. /// The other source to perform except with. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateExcept( + protected abstract ShapedQueryExpression? TranslateExcept( [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); @@ -782,7 +782,7 @@ protected abstract ShapedQueryExpression TranslateExcept( /// The return type of result. /// A value indicating whether default should be returned or throw. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateFirstOrDefault( + protected abstract ShapedQueryExpression? TranslateFirstOrDefault( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? predicate, [NotNull] Type returnType, @@ -797,7 +797,7 @@ protected abstract ShapedQueryExpression TranslateFirstOrDefault( /// The element selector supplied in the call. /// The result selector supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateGroupBy( + protected abstract ShapedQueryExpression? TranslateGroupBy( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression keySelector, [CanBeNull] LambdaExpression? elementSelector, @@ -815,7 +815,7 @@ protected abstract ShapedQueryExpression TranslateGroupBy( /// The key selector for the inner source. /// The result selector supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateGroupJoin( + protected abstract ShapedQueryExpression? TranslateGroupJoin( [NotNull] ShapedQueryExpression outer, [NotNull] ShapedQueryExpression inner, [NotNull] LambdaExpression outerKeySelector, @@ -828,7 +828,7 @@ protected abstract ShapedQueryExpression TranslateGroupJoin( /// The shaped query on which the operator is applied. /// The other source to perform intersect with. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateIntersect( + protected abstract ShapedQueryExpression? TranslateIntersect( [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); @@ -844,7 +844,7 @@ protected abstract ShapedQueryExpression TranslateIntersect( /// The key selector for the inner source. /// The result selector supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateJoin( + protected abstract ShapedQueryExpression? TranslateJoin( [NotNull] ShapedQueryExpression outer, [NotNull] ShapedQueryExpression inner, [NotNull] LambdaExpression outerKeySelector, @@ -866,7 +866,7 @@ protected abstract ShapedQueryExpression TranslateJoin( /// The key selector for the inner source. /// The result selector supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateLeftJoin( + protected abstract ShapedQueryExpression? TranslateLeftJoin( [NotNull] ShapedQueryExpression outer, [NotNull] ShapedQueryExpression inner, [NotNull] LambdaExpression outerKeySelector, @@ -882,7 +882,7 @@ protected abstract ShapedQueryExpression TranslateLeftJoin( /// The return type of result. /// A value indicating whether default should be returned or throw. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateLastOrDefault( + protected abstract ShapedQueryExpression? TranslateLastOrDefault( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? predicate, [NotNull] Type returnType, @@ -894,7 +894,7 @@ protected abstract ShapedQueryExpression TranslateLastOrDefault( /// The shaped query on which the operator is applied. /// The predicate supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateLongCount( + protected abstract ShapedQueryExpression? TranslateLongCount( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? predicate); @@ -905,7 +905,7 @@ protected abstract ShapedQueryExpression TranslateLongCount( /// The selector supplied in the call. /// The result type after the operation. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateMax( + protected abstract ShapedQueryExpression? TranslateMax( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? selector, [NotNull] Type resultType); @@ -917,7 +917,7 @@ protected abstract ShapedQueryExpression TranslateMax( /// The selector supplied in the call. /// The result type after the operation. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateMin( + protected abstract ShapedQueryExpression? TranslateMin( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? selector, [NotNull] Type resultType); @@ -928,7 +928,7 @@ protected abstract ShapedQueryExpression TranslateMin( /// The shaped query on which the operator is applied. /// The type of result which is being filtered with. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateOfType([NotNull] ShapedQueryExpression source, [NotNull] Type resultType); + protected abstract ShapedQueryExpression? TranslateOfType([NotNull] ShapedQueryExpression source, [NotNull] Type resultType); /// /// Translates or @@ -939,7 +939,7 @@ protected abstract ShapedQueryExpression TranslateMin( /// The key selector supplied in the call. /// A value indicating whether the ordering is ascending or not. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateOrderBy( + protected abstract ShapedQueryExpression? TranslateOrderBy( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression keySelector, bool ascending); @@ -949,7 +949,7 @@ protected abstract ShapedQueryExpression TranslateOrderBy( /// /// The shaped query on which the operator is applied. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateReverse([NotNull] ShapedQueryExpression source); + protected abstract ShapedQueryExpression? TranslateReverse([NotNull] ShapedQueryExpression source); /// /// Translates method over the @@ -972,7 +972,7 @@ protected abstract ShapedQueryExpression TranslateSelect( /// The collection selector supplied in the call. /// The result selector supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateSelectMany( + protected abstract ShapedQueryExpression? TranslateSelectMany( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression collectionSelector, [NotNull] LambdaExpression resultSelector); @@ -984,7 +984,7 @@ protected abstract ShapedQueryExpression TranslateSelectMany( /// The shaped query on which the operator is applied. /// The selector supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateSelectMany( + protected abstract ShapedQueryExpression? TranslateSelectMany( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression selector); @@ -998,7 +998,7 @@ protected abstract ShapedQueryExpression TranslateSelectMany( /// The return type of result. /// A value indicating whether default should be returned or throw. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateSingleOrDefault( + protected abstract ShapedQueryExpression? TranslateSingleOrDefault( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? predicate, [NotNull] Type returnType, @@ -1010,7 +1010,7 @@ protected abstract ShapedQueryExpression TranslateSingleOrDefault( /// The shaped query on which the operator is applied. /// The count supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateSkip( + protected abstract ShapedQueryExpression? TranslateSkip( [NotNull] ShapedQueryExpression source, [NotNull] Expression count); @@ -1021,7 +1021,7 @@ protected abstract ShapedQueryExpression TranslateSkip( /// The shaped query on which the operator is applied. /// The predicate supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateSkipWhile( + protected abstract ShapedQueryExpression? TranslateSkipWhile( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); @@ -1032,7 +1032,7 @@ protected abstract ShapedQueryExpression TranslateSkipWhile( /// The selector supplied in the call. /// The result type after the operation. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateSum( + protected abstract ShapedQueryExpression? TranslateSum( [NotNull] ShapedQueryExpression source, [CanBeNull] LambdaExpression? selector, [NotNull] Type resultType); @@ -1043,7 +1043,7 @@ protected abstract ShapedQueryExpression TranslateSum( /// The shaped query on which the operator is applied. /// The count supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateTake([NotNull] ShapedQueryExpression source, [NotNull] Expression count); + protected abstract ShapedQueryExpression? TranslateTake([NotNull] ShapedQueryExpression source, [NotNull] Expression count); /// /// Translates method over the given @@ -1052,7 +1052,7 @@ protected abstract ShapedQueryExpression TranslateSum( /// The shaped query on which the operator is applied. /// The predicate supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateTakeWhile( + protected abstract ShapedQueryExpression? TranslateTakeWhile( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); @@ -1065,7 +1065,7 @@ protected abstract ShapedQueryExpression TranslateTakeWhile( /// The key selector supplied in the call. /// A value indicating whether the ordering is ascending or not. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateThenBy( + protected abstract ShapedQueryExpression? TranslateThenBy( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression keySelector, bool ascending); @@ -1076,7 +1076,7 @@ protected abstract ShapedQueryExpression TranslateThenBy( /// The shaped query on which the operator is applied. /// The other source to perform union with. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateUnion( + protected abstract ShapedQueryExpression? TranslateUnion( [NotNull] ShapedQueryExpression source1, [NotNull] ShapedQueryExpression source2); @@ -1086,7 +1086,7 @@ protected abstract ShapedQueryExpression TranslateUnion( /// The shaped query on which the operator is applied. /// The predicate supplied in the call. /// The shaped query after translation. - protected abstract ShapedQueryExpression TranslateWhere( + protected abstract ShapedQueryExpression? TranslateWhere( [NotNull] ShapedQueryExpression source, [NotNull] LambdaExpression predicate); }