diff --git a/Directory.Build.props b/Directory.Build.props index f9bb135989c..dd083405cee 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -16,16 +16,13 @@ Apache-2.0 - - net5.0 - - MicrosoftAspNetCore Entity Framework Core;entity-framework-core;EF;Data;O/RM;EntityFramework;EntityFrameworkCore;EFCore Microsoft Entity Framework Core true - 8.0 + nullable + 9.0 portable https://docs.microsoft.com/ef/core/ diff --git a/benchmark/EFCore.Benchmarks/EFCore.Benchmarks.csproj b/benchmark/EFCore.Benchmarks/EFCore.Benchmarks.csproj index 57aeca4b90b..9d1460f2963 100644 --- a/benchmark/EFCore.Benchmarks/EFCore.Benchmarks.csproj +++ b/benchmark/EFCore.Benchmarks/EFCore.Benchmarks.csproj @@ -1,34 +1,17 @@  - net461;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1 - netcoreapp3.1 + net5.0 Microsoft.EntityFrameworkCore.Benchmarks - + true - + - - - - - - - - - - - - - - $(DefineConstants);OLD_FROM_SQL - - diff --git a/benchmark/EFCore.SqlServer.Benchmarks/EFCore.SqlServer.Benchmarks.csproj b/benchmark/EFCore.SqlServer.Benchmarks/EFCore.SqlServer.Benchmarks.csproj index bf78031a101..805190f619a 100644 --- a/benchmark/EFCore.SqlServer.Benchmarks/EFCore.SqlServer.Benchmarks.csproj +++ b/benchmark/EFCore.SqlServer.Benchmarks/EFCore.SqlServer.Benchmarks.csproj @@ -1,30 +1,18 @@  - net461;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1 - netcoreapp3.1 + net5.0 Microsoft.EntityFrameworkCore.Benchmarks Exe - + true - + - - - - - - - - - - - - + @@ -34,8 +22,4 @@ - - - - diff --git a/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj b/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj index 15da48e2843..d609d1abb64 100644 --- a/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj +++ b/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj @@ -1,42 +1,26 @@  - net461;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1 - netcoreapp3.1 + net5.0 Microsoft.EntityFrameworkCore.Benchmarks Exe - + true - - - - + - - - - - - - - - - - - Always diff --git a/benchmark/EFCore.Sqlite.Benchmarks/Models/AdventureWorks/AdventureWorksSqliteFixture.cs b/benchmark/EFCore.Sqlite.Benchmarks/Models/AdventureWorks/AdventureWorksSqliteFixture.cs index c40a33e1f5d..79134a4bf57 100644 --- a/benchmark/EFCore.Sqlite.Benchmarks/Models/AdventureWorks/AdventureWorksSqliteFixture.cs +++ b/benchmark/EFCore.Sqlite.Benchmarks/Models/AdventureWorks/AdventureWorksSqliteFixture.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.IO; namespace Microsoft.EntityFrameworkCore.Benchmarks.Models.AdventureWorks @@ -9,7 +8,7 @@ namespace Microsoft.EntityFrameworkCore.Benchmarks.Models.AdventureWorks public static class AdventureWorksSqliteFixture { private static readonly string _baseDirectory - = Path.GetDirectoryName(new Uri(typeof(AdventureWorksSqliteFixture).Assembly.CodeBase).LocalPath); + = Path.GetDirectoryName(typeof(AdventureWorksSqliteFixture).Assembly.Location); private static readonly string _connectionString = $"Data Source={Path.Combine(_baseDirectory, "AdventureWorks2014.db")}"; diff --git a/benchmark/EFCore.Sqlite.Benchmarks/Models/Orders/OrdersSqliteFixture.cs b/benchmark/EFCore.Sqlite.Benchmarks/Models/Orders/OrdersSqliteFixture.cs index 4526d3c6887..8e7ff4e3108 100644 --- a/benchmark/EFCore.Sqlite.Benchmarks/Models/Orders/OrdersSqliteFixture.cs +++ b/benchmark/EFCore.Sqlite.Benchmarks/Models/Orders/OrdersSqliteFixture.cs @@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Benchmarks.Models.Orders public class OrdersSqliteFixture : OrdersFixtureBase { private static readonly string _baseDirectory - = Path.GetDirectoryName(new Uri(typeof(OrdersSqliteFixture).Assembly.CodeBase).LocalPath); + = Path.GetDirectoryName(typeof(OrdersSqliteFixture).Assembly.Location); private readonly string _connectionString; diff --git a/src/EFCore.Abstractions/EFCore.Abstractions.csproj b/src/EFCore.Abstractions/EFCore.Abstractions.csproj index 1826da4d11f..b38320dbb1f 100644 --- a/src/EFCore.Abstractions/EFCore.Abstractions.csproj +++ b/src/EFCore.Abstractions/EFCore.Abstractions.csproj @@ -2,7 +2,7 @@ Provides abstractions and attributes that are used to configure Entity Framework Core - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.Abstractions Microsoft.EntityFrameworkCore diff --git a/src/EFCore.Cosmos/EFCore.Cosmos.csproj b/src/EFCore.Cosmos/EFCore.Cosmos.csproj index 1f426f7b52d..7963c870192 100644 --- a/src/EFCore.Cosmos/EFCore.Cosmos.csproj +++ b/src/EFCore.Cosmos/EFCore.Cosmos.csproj @@ -2,7 +2,7 @@ Azure Cosmos provider for Entity Framework Core. - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.Cosmos Microsoft.EntityFrameworkCore.Cosmos diff --git a/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs index 9448a7e52e7..968f2dd2acf 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -19,9 +20,7 @@ namespace Microsoft.EntityFrameworkCore public static class CosmosQueryableExtensions { internal static readonly MethodInfo WithPartitionKeyMethodInfo - = typeof(CosmosQueryableExtensions) - .GetTypeInfo() - .GetDeclaredMethod(nameof(WithPartitionKey)); + = typeof(CosmosQueryableExtensions).GetRequiredDeclaredMethod(nameof(WithPartitionKey)); /// /// Specify the partition key for partition used for the query. Required when using @@ -33,7 +32,7 @@ internal static readonly MethodInfo WithPartitionKeyMethodInfo /// A new query with the set partition key. public static IQueryable WithPartitionKey( [NotNull] this IQueryable source, - [NotNull] [NotParameterized] string partitionKey) + [NotNull][NotParameterized] string partitionKey) where TEntity : class { Check.NotNull(source, nameof(source)); diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryMetadataExtractingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryMetadataExtractingExpressionVisitor.cs index 95561fdaba5..7be71a4b7b9 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryMetadataExtractingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryMetadataExtractingExpressionVisitor.cs @@ -44,8 +44,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp { var innerQueryable = Visit(methodCallExpression.Arguments[0]); - _cosmosQueryCompilationContext.PartitionKeyFromExtension = - (string)((ConstantExpression)methodCallExpression.Arguments[1]).Value; + _cosmosQueryCompilationContext.PartitionKeyFromExtension = methodCallExpression.Arguments[1].GetConstantValue(); return innerQueryable; } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs index 9efbef8fc21..00a6900ced1 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitor.cs @@ -30,7 +30,7 @@ protected override ProjectionExpression GetProjection(ProjectionBindingExpressio private int GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression) => projectionBindingExpression.ProjectionMember != null - ? (int)((ConstantExpression)_selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value + ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember).GetConstantValue() : projectionBindingExpression.Index ?? throw new InvalidOperationException(CoreStrings.QueryFailed(projectionBindingExpression.Print(), GetType().Name)); } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs index 63d948da8e4..f45891ee85a 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs @@ -185,7 +185,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp var genericMethod = method.IsGenericMethod ? method.GetGenericMethodDefinition() : null; if (genericMethod == EntityFrameworkCore.Infrastructure.ExpressionExtensions.ValueBufferTryReadValueMethod) { - var property = (IProperty)((ConstantExpression)methodCallExpression.Arguments[2]).Value; + var property = methodCallExpression.Arguments[2].GetConstantValue(); Expression innerExpression; if (methodCallExpression.Arguments[0] is ProjectionBindingExpression projectionBindingExpression) { diff --git a/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs index 9ae14e80e65..a7447b13ff5 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs @@ -44,7 +44,7 @@ public SqlConstantExpression([NotNull] ConstantExpression constantExpression, [C /// 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 Value + public virtual object? Value => _constantExpression.Value; /// @@ -83,7 +83,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) } private void Print( - object value, + object? value, ExpressionPrinter expressionPrinter) { if (value is IEnumerable enumerable @@ -110,7 +110,7 @@ private void Print( } } - private JToken? GenerateJToken(object value, CoreTypeMapping? typeMapping) + private JToken? GenerateJToken(object? value, CoreTypeMapping? typeMapping) { var mappingClrType = typeMapping?.ClrType.UnwrapNullableType() ?? Type; if (value?.GetType().IsInteger() == true diff --git a/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs index c19d9758832..3a1f03cf511 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs @@ -21,6 +21,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal public sealed class SqlParameterExpression : SqlExpression { private readonly ParameterExpression _parameterExpression; + private readonly string _name; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -31,7 +32,10 @@ public sealed class SqlParameterExpression : SqlExpression public SqlParameterExpression([NotNull] ParameterExpression parameterExpression, [CanBeNull] CoreTypeMapping? typeMapping) : base(parameterExpression.Type, typeMapping) { + Check.DebugAssert(parameterExpression.Name != null, "Parameter must have name."); + _parameterExpression = parameterExpression; + _name = parameterExpression.Name; } /// @@ -41,7 +45,7 @@ public SqlParameterExpression([NotNull] ParameterExpression parameterExpression, /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public string Name - => _parameterExpression.Name; + => _name; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs b/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs index dcc3e6e686c..82adc07ab49 100644 --- a/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs @@ -22,13 +22,13 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal public class StringMethodTranslator : IMethodCallTranslator { private static readonly MethodInfo _containsMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); private static readonly MethodInfo _startsWithMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); private static readonly MethodInfo _endsWithMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); private static readonly MethodInfo _firstOrDefaultMethodInfoWithoutArgs = typeof(Enumerable).GetRuntimeMethods().Single( diff --git a/src/EFCore.Design/EFCore.Design.csproj b/src/EFCore.Design/EFCore.Design.csproj index 5ba1cc823c6..ea9b3b0e3a1 100644 --- a/src/EFCore.Design/EFCore.Design.csproj +++ b/src/EFCore.Design/EFCore.Design.csproj @@ -2,7 +2,7 @@ Shared design-time components for Entity Framework Core tools. - netstandard2.1 + net5.0 Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore true @@ -31,7 +31,6 @@ - diff --git a/src/EFCore.Design/build/netcoreapp3.0/Microsoft.EntityFrameworkCore.Design.props b/src/EFCore.Design/build/net5.0/Microsoft.EntityFrameworkCore.Design.props similarity index 100% rename from src/EFCore.Design/build/netcoreapp3.0/Microsoft.EntityFrameworkCore.Design.props rename to src/EFCore.Design/build/net5.0/Microsoft.EntityFrameworkCore.Design.props diff --git a/src/EFCore.InMemory/EFCore.InMemory.csproj b/src/EFCore.InMemory/EFCore.InMemory.csproj index 4ce6274ada6..b400607e4a9 100644 --- a/src/EFCore.InMemory/EFCore.InMemory.csproj +++ b/src/EFCore.InMemory/EFCore.InMemory.csproj @@ -2,7 +2,7 @@ In-memory database provider for Entity Framework Core (to be used for testing purposes). - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.InMemory Microsoft.EntityFrameworkCore.InMemory diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index 77e11725141..97274768353 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -37,22 +37,22 @@ public class InMemoryExpressionTranslatingExpressionVisitor : ExpressionVisitor private static readonly MemberInfo _valueBufferIsEmpty = typeof(ValueBuffer).GetMember(nameof(ValueBuffer.IsEmpty))[0]; private static readonly MethodInfo _parameterValueExtractor = - typeof(InMemoryExpressionTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(ParameterValueExtractor)); + typeof(InMemoryExpressionTranslatingExpressionVisitor).GetRequiredDeclaredMethod(nameof(ParameterValueExtractor)); private static readonly MethodInfo _parameterListValueExtractor = - typeof(InMemoryExpressionTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(ParameterListValueExtractor)); + typeof(InMemoryExpressionTranslatingExpressionVisitor).GetRequiredDeclaredMethod(nameof(ParameterListValueExtractor)); private static readonly MethodInfo _getParameterValueMethodInfo = - typeof(InMemoryExpressionTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(GetParameterValue)); + typeof(InMemoryExpressionTranslatingExpressionVisitor).GetRequiredDeclaredMethod(nameof(GetParameterValue)); - private static readonly MethodInfo _likeMethodInfo = typeof(DbFunctionsExtensions).GetRuntimeMethod( + private static readonly MethodInfo _likeMethodInfo = typeof(DbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), typeof(string), typeof(string) }); - private static readonly MethodInfo _likeMethodInfoWithEscape = typeof(DbFunctionsExtensions).GetRuntimeMethod( + private static readonly MethodInfo _likeMethodInfoWithEscape = typeof(DbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), typeof(string), typeof(string), typeof(string) }); private static readonly MethodInfo _inMemoryLikeMethodInfo = - typeof(InMemoryExpressionTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(InMemoryLike)); + typeof(InMemoryExpressionTranslatingExpressionVisitor).GetRequiredDeclaredMethod(nameof(InMemoryLike)); // Regex special chars defined here: // https://msdn.microsoft.com/en-us/library/4edbef7e(v=vs.110).aspx @@ -134,7 +134,8 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) { var result = Visit(expression); - return _entityReferenceFindingExpressionVisitor.Find(result) + return result == QueryCompilationContext.NotTranslatedExpression + || _entityReferenceFindingExpressionVisitor.Find(result) ? null : result; } @@ -145,7 +146,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. /// - protected override Expression? VisitBinary(BinaryExpression binaryExpression) + protected override Expression VisitBinary(BinaryExpression binaryExpression) { Check.NotNull(binaryExpression, nameof(binaryExpression)); @@ -159,10 +160,10 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) var newLeft = Visit(binaryExpression.Left); var newRight = Visit(binaryExpression.Right); - if (newLeft == null - || newRight == null) + if (newLeft == QueryCompilationContext.NotTranslatedExpression + || newRight == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if ((binaryExpression.NodeType == ExpressionType.Equal @@ -225,7 +226,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. /// - protected override Expression? VisitConditional(ConditionalExpression conditionalExpression) + protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { Check.NotNull(conditionalExpression, nameof(conditionalExpression)); @@ -233,11 +234,11 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) var ifTrue = Visit(conditionalExpression.IfTrue); var ifFalse = Visit(conditionalExpression.IfFalse); - if (test == null - || ifTrue == null - || ifFalse == null) + if (test == QueryCompilationContext.NotTranslatedExpression + || ifTrue == QueryCompilationContext.NotTranslatedExpression + || ifFalse == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (test.Type == typeof(bool?)) @@ -261,7 +262,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. /// - protected override Expression? VisitExtension(Expression extensionExpression) + protected override Expression VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); @@ -278,7 +279,7 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) return projectionBindingExpression.ProjectionMember != null ? ((InMemoryQueryExpression)projectionBindingExpression.QueryExpression) .GetMappedProjection(projectionBindingExpression.ProjectionMember) - : null; + : QueryCompilationContext.NotTranslatedExpression; case InMemoryGroupByShaperExpression inMemoryGroupByShaperExpression: return new GroupingElementExpression( @@ -287,7 +288,7 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) inMemoryGroupByShaperExpression.ValueBufferParameter); default: - return null; + return QueryCompilationContext.NotTranslatedExpression; } } @@ -297,8 +298,8 @@ 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. /// - protected override Expression? VisitInvocation(InvocationExpression invocationExpression) - => null; + protected override Expression VisitInvocation(InvocationExpression invocationExpression) + => QueryCompilationContext.NotTranslatedExpression; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -306,8 +307,8 @@ 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. /// - protected override Expression? VisitLambda(Expression lambdaExpression) - => null; + protected override Expression VisitLambda(Expression lambdaExpression) + => QueryCompilationContext.NotTranslatedExpression; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -315,8 +316,8 @@ 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. /// - protected override Expression? VisitListInit(ListInitExpression listInitExpression) - => null; + protected override Expression VisitListInit(ListInitExpression listInitExpression) + => QueryCompilationContext.NotTranslatedExpression; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -324,15 +325,15 @@ 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. /// - protected override Expression? VisitMember(MemberExpression memberExpression) + protected override Expression VisitMember(MemberExpression memberExpression) { Check.NotNull(memberExpression, nameof(memberExpression)); var innerExpression = Visit(memberExpression.Expression); if (memberExpression.Expression != null - && innerExpression == null) + && innerExpression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (TryBindMember(innerExpression, MemberIdentity.Create(memberExpression.Member), memberExpression.Type) is Expression result) @@ -367,12 +368,12 @@ 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) + if (expression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return memberAssignment.Update(Expression.Convert(expression, memberAssignment.Expression.Type)); } if (IsConvertedToNullable(expression, memberAssignment.Expression)) @@ -389,7 +390,43 @@ 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 Expression? VisitMethodCall(MethodCallExpression methodCallExpression) + protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) + { + Check.NotNull(memberInitExpression, nameof(memberInitExpression)); + + var newExpression = Visit(memberInitExpression.NewExpression); + if (newExpression == QueryCompilationContext.NotTranslatedExpression) + { + return QueryCompilationContext.NotTranslatedExpression; + } + + var newBindings = new MemberBinding[memberInitExpression.Bindings.Count]; + for (var i = 0; i < newBindings.Length; i++) + { + if (memberInitExpression.Bindings[i].BindingType != MemberBindingType.Assignment) + { + return QueryCompilationContext.NotTranslatedExpression; + } + + newBindings[i] = VisitMemberBinding(memberInitExpression.Bindings[i]); + if (((MemberAssignment)newBindings[i]).Expression is UnaryExpression unaryExpression + && unaryExpression.NodeType == ExpressionType.Convert + && unaryExpression.Operand == QueryCompilationContext.NotTranslatedExpression) + { + return QueryCompilationContext.NotTranslatedExpression; + } + } + + return memberInitExpression.Update((NewExpression)newExpression, newBindings); + } + + /// + /// 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. + /// + protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); @@ -409,7 +446,8 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem // EF Indexer property if (methodCallExpression.TryGetIndexerArguments(_model, out source, out propertyName)) { - return TryBindMember(Visit(source), MemberIdentity.Create(propertyName), methodCallExpression.Type); + return TryBindMember(Visit(source), MemberIdentity.Create(propertyName), methodCallExpression.Type) + ?? QueryCompilationContext.NotTranslatedExpression; } // GroupBy Aggregate case @@ -436,7 +474,7 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem result = expression == null ? null : Expression.Call( - EnumerableMethods.GetAverageWithoutSelector(expression.Type.TryGetSequenceType()!), expression); + EnumerableMethods.GetAverageWithoutSelector(expression.Type.GetSequenceType()), expression); break; } @@ -461,7 +499,7 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem result = expression == null ? null : Expression.Call( - EnumerableMethods.CountWithoutPredicate.MakeGenericMethod(expression.Type.TryGetSequenceType()), + EnumerableMethods.CountWithoutPredicate.MakeGenericMethod(expression.Type.GetSequenceType()), expression); break; } @@ -495,7 +533,7 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem result = expression == null ? null : Expression.Call( - EnumerableMethods.LongCountWithoutPredicate.MakeGenericMethod(expression.Type.TryGetSequenceType()), + EnumerableMethods.LongCountWithoutPredicate.MakeGenericMethod(expression.Type.GetSequenceType()), expression); break; } @@ -516,7 +554,7 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem } else { - var type = expression.Type.TryGetSequenceType()!; + var type = expression.Type.GetSequenceType(); var aggregateMethod = EnumerableMethods.GetMaxWithoutSelector(type); if (aggregateMethod.IsGenericMethod) { @@ -545,7 +583,7 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem } else { - var type = expression.Type.TryGetSequenceType()!; + var type = expression.Type.GetSequenceType(); var aggregateMethod = EnumerableMethods.GetMinWithoutSelector(type); if (aggregateMethod.IsGenericMethod) { @@ -575,7 +613,7 @@ static bool ShouldApplyNullProtectionForMemberAccess(Type callerType, string mem result = expression == null ? null : Expression.Call( - EnumerableMethods.GetSumWithoutSelector(expression.Type.TryGetSequenceType()!), expression); + EnumerableMethods.GetSumWithoutSelector(expression.Type.GetSequenceType()), expression); break; } @@ -651,7 +689,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE var subquery = (InMemoryQueryExpression)subqueryTranslation.QueryExpression; if (subqueryTranslation.ResultCardinality == ResultCardinality.Enumerable) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var shaperExpression = subqueryTranslation.ShaperExpression; @@ -675,13 +713,13 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE && (convertedType == null || convertedType.MakeNullable() == innerExpression.Type))) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (projectionBindingExpression.ProjectionMember == null) { // We don't lift scalar subquery with client eval - return null; + return QueryCompilationContext.NotTranslatedExpression; } return ProcessSingleResultScalar( @@ -703,7 +741,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE var argument = Visit(methodCallExpression.Arguments[i]); if (TranslationFailed(methodCallExpression.Arguments[i], argument)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } visitedArguments[i - 1] = argument; @@ -721,22 +759,22 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE && methodCallExpression.Arguments.Count == 1) { var left = Visit(methodCallExpression.Object); - var right = Visit(methodCallExpression.Arguments[0]); + var right = Visit(methodCallExpression.Arguments[0])!; if (TryRewriteEntityEquality( ExpressionType.Equal, - left ?? methodCallExpression.Object, - right ?? methodCallExpression.Arguments[0], + left == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Object : left, + right == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[0] : right, equalsMethod: true, out var result)) { return result; } - if (TranslationFailed(left) - || TranslationFailed(right)) + if (TranslationFailed(methodCallExpression.Object, left) + || TranslationFailed(methodCallExpression.Arguments[0], right)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } @object = left; @@ -754,23 +792,23 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE methodCallExpression.Arguments[0], methodCallExpression.Arguments[1])); } - var left = Visit(methodCallExpression.Arguments[0]); - var right = Visit(methodCallExpression.Arguments[1]); + var left = Visit(methodCallExpression.Arguments[0])!; + var right = Visit(methodCallExpression.Arguments[1])!; if (TryRewriteEntityEquality( ExpressionType.Equal, - left ?? methodCallExpression.Arguments[0], - right ?? methodCallExpression.Arguments[1], + left == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[0] : left, + right == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[1] : right, equalsMethod: true, out var result)) { return result; } - if (TranslationFailed(left) - || TranslationFailed(right)) + if (TranslationFailed(methodCallExpression.Arguments[0], left) + || TranslationFailed(methodCallExpression.Arguments[1], right)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } arguments = new Expression[2] { left, right }; @@ -778,18 +816,20 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE else if (method.IsGenericMethod && method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains)) { - var enumerable = Visit(methodCallExpression.Arguments[0]); - var item = Visit(methodCallExpression.Arguments[1]); + var enumerable = Visit(methodCallExpression.Arguments[0])!; + var item = Visit(methodCallExpression.Arguments[1])!; - if (TryRewriteContainsEntity(enumerable, item ?? methodCallExpression.Arguments[1], out var result)) + if (TryRewriteContainsEntity(enumerable, + item == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[1] : item, + out var result)) { return result; } - if (TranslationFailed(enumerable) - || TranslationFailed(item)) + if (TranslationFailed(methodCallExpression.Arguments[0], enumerable) + || TranslationFailed(methodCallExpression.Arguments[1], item)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } arguments = new Expression[2] { enumerable, item }; @@ -798,17 +838,19 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE && method.IsContainsMethod()) { var enumerable = Visit(methodCallExpression.Object); - var item = Visit(methodCallExpression.Arguments[0]); + var item = Visit(methodCallExpression.Arguments[0])!; - if (TryRewriteContainsEntity(enumerable, item ?? methodCallExpression.Arguments[0], out var result)) + if (TryRewriteContainsEntity(enumerable, + item == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[0] : item, + out var result)) { return result; } - if (TranslationFailed(enumerable) - || TranslationFailed(item)) + if (TranslationFailed(methodCallExpression.Object, enumerable) + || TranslationFailed(methodCallExpression.Arguments[0], item)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } @object = enumerable; @@ -819,7 +861,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE @object = Visit(methodCallExpression.Object); if (TranslationFailed(methodCallExpression.Object, @object)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } arguments = new Expression[methodCallExpression.Arguments.Count]; @@ -828,7 +870,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE var argument = Visit(methodCallExpression.Arguments[i]); if (TranslationFailed(methodCallExpression.Arguments[i], argument)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } arguments[i] = argument; @@ -869,7 +911,8 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE return result; } - return methodCallExpression.Update(@object, arguments); + // TODO-Nullable bug + return methodCallExpression.Update(@object!, arguments); } /// @@ -878,7 +921,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)); @@ -886,9 +929,9 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE foreach (var argument in newExpression.Arguments) { var newArgument = Visit(argument); - if (newArgument == null) + if (newArgument == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (IsConvertedToNullable(newArgument, argument)) @@ -908,7 +951,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? VisitNewArray(NewArrayExpression newArrayExpression) + protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) { Check.NotNull(newArrayExpression, nameof(newArrayExpression)); @@ -916,9 +959,9 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE foreach (var expression in newArrayExpression.Expressions) { var newExpression = Visit(expression); - if (newExpression == null) + if (newExpression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (IsConvertedToNullable(newExpression, expression)) @@ -938,7 +981,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? VisitParameter(ParameterExpression parameterExpression) + protected override Expression VisitParameter(ParameterExpression parameterExpression) { Check.NotNull(parameterExpression, nameof(parameterExpression)); @@ -959,7 +1002,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? VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) + protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); @@ -999,7 +1042,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE } } - return null; + return QueryCompilationContext.NotTranslatedExpression; } /// @@ -1008,14 +1051,14 @@ 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? VisitUnary(UnaryExpression unaryExpression) + protected override Expression VisitUnary(UnaryExpression unaryExpression) { Check.NotNull(unaryExpression, nameof(unaryExpression)); var newOperand = Visit(unaryExpression.Operand); - if (newOperand == null) + if (newOperand == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (newOperand is EntityReferenceExpression entityReferenceExpression @@ -1063,7 +1106,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE 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)) { @@ -1093,8 +1136,13 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE { if (entityReferenceExpression.ParameterEntity != null) { - var result = ((EntityProjectionExpression)Visit(entityReferenceExpression.ParameterEntity.ValueBufferExpression)) - .BindProperty(property); + var valueBufferExpression = Visit(entityReferenceExpression.ParameterEntity.ValueBufferExpression); + if (valueBufferExpression == QueryCompilationContext.NotTranslatedExpression) + { + return null; + } + + var result = ((EntityProjectionExpression)valueBufferExpression).BindProperty(property); // if the result type change was just nullability change e.g from int to int? // we want to preserve the new type for null propagation @@ -1174,7 +1222,7 @@ private static Expression ProcessSingleResultScalar( [UsedImplicitly] private static T GetParameterValue(QueryContext queryContext, string parameterName) - => (T)queryContext.ParameterValues[parameterName]; + => (T)queryContext.ParameterValues[parameterName]!; private static bool IsConvertedToNullable(Expression result, Expression original) => result.Type.IsNullableType() @@ -1205,13 +1253,13 @@ private static Expression ConvertToNonNullable(Expression expression) && readValueMethodCall.Method.IsGenericMethod && readValueMethodCall.Method.GetGenericMethodDefinition() == ExpressionExtensions.ValueBufferTryReadValueMethod) { - return (IProperty)((ConstantExpression)readValueMethodCall.Arguments[2]).Value; + return readValueMethodCall.Arguments[2].GetConstantValue(); } return null; } - private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.NotNullWhen(true)] out Expression? result) + private bool TryRewriteContainsEntity(Expression? source, Expression item, [CA.NotNullWhen(true)] out Expression? result) { result = null; @@ -1239,9 +1287,9 @@ private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.No switch (source) { case ConstantExpression constantExpression: - var values = (IEnumerable)constantExpression.Value; + var values = constantExpression.GetConstantValue(); var propertyValueList = - (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(property.ClrType.MakeNullable())); + (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(property.ClrType.MakeNullable()))!; var propertyGetter = property.GetGetter(); foreach (var value in values) { @@ -1254,10 +1302,10 @@ private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.No case MethodCallExpression methodCallExpression when methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == _getParameterValueMethodInfo: - var parameterName = (string)((ConstantExpression)methodCallExpression.Arguments[1]).Value; + var parameterName = methodCallExpression.Arguments[1].GetConstantValue(); var lambda = Expression.Lambda( Expression.Call( - _parameterListValueExtractor.MakeGenericMethod(entityType.ClrType, property.ClrType.MakeNullable()), + _parameterListValueExtractor.MakeGenericMethod(entityType.ClrType!, property.ClrType.MakeNullable()), QueryCompilationContext.QueryContextParameter, Expression.Constant(parameterName, typeof(string)), Expression.Constant(property, typeof(IProperty))), @@ -1381,7 +1429,7 @@ private Expression CreatePropertyAccessExpression(Expression target, IProperty p case MethodCallExpression methodCallExpression when methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == _getParameterValueMethodInfo: - var parameterName = (string)((ConstantExpression)methodCallExpression.Arguments[1]).Value; + var parameterName = methodCallExpression.Arguments[1].GetConstantValue(); var lambda = Expression.Lambda( Expression.Call( _parameterValueExtractor.MakeGenericMethod(property.ClrType.MakeNullable()), @@ -1504,10 +1552,8 @@ private static bool IsNullConstantExpression(Expression expression) [DebuggerStepThrough] private static bool TranslationFailed(Expression? original, Expression? translation) - => original != null && TranslationFailed(translation); - - private static bool TranslationFailed([CA.NotNullWhen(false)] Expression? translation) - => translation == null || translation is EntityReferenceExpression; + => original != null + && (translation == QueryCompilationContext.NotTranslatedExpression || translation is EntityReferenceExpression); private static bool InMemoryLike(string matchExpression, string pattern, string escapeCharacter) { @@ -1603,7 +1649,8 @@ public bool Find(Expression expression) return _found; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { if (_found) { @@ -1652,7 +1699,7 @@ public override Type Type 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 @@ -1662,7 +1709,9 @@ public override ExpressionType NodeType var derivedEntityType = EntityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type); - return derivedEntityType == null ? null : new EntityReferenceExpression(this, derivedEntityType); + return derivedEntityType == null + ? QueryCompilationContext.NotTranslatedExpression + : new EntityReferenceExpression(this, derivedEntityType); } } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs index 01ba22955e7..52e47c5051c 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs @@ -12,6 +12,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -67,7 +68,7 @@ public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpre var expandedExpression = _queryableMethodTranslatingExpressionVisitor.ExpandWeakEntities(_queryExpression, expression); var result = Visit(expandedExpression); - if (result == null) + if (result == QueryCompilationContext.NotTranslatedExpression) { _clientEval = true; @@ -93,6 +94,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. /// + [return: CA.NotNullIfNotNull("expression")] public override Expression? Visit(Expression? expression) { if (expression == null) @@ -125,7 +127,7 @@ public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpre _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( materializeCollectionNavigationExpression.Subquery)!, materializeCollectionNavigationExpression.Navigation, - materializeCollectionNavigationExpression.Navigation.ClrType.TryGetSequenceType()!); + materializeCollectionNavigationExpression.Navigation.ClrType.GetSequenceType()); case MethodCallExpression methodCallExpression: { @@ -179,7 +181,7 @@ public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpre var translation = _expressionTranslatingExpressionVisitor.Translate(expression); if (translation == null) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } _projectionMapping[_projectionMembers.Peek()] = translation; @@ -199,8 +201,8 @@ public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpre /// 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); } @@ -213,9 +215,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?)) { @@ -231,7 +233,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)); @@ -243,7 +245,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional if (projectionBindingExpression.ProjectionMember == null) { // We don't process binding with client projection - return null; + return QueryCompilationContext.NotTranslatedExpression; } entityProjectionExpression = (EntityProjectionExpression)((InMemoryQueryExpression)projectionBindingExpression.QueryExpression) @@ -270,7 +272,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional { return _clientEval ? base.VisitExtension(includeExpression) - : null; + : QueryCompilationContext.NotTranslatedExpression; } throw new InvalidOperationException(CoreStrings.QueryFailed(extensionExpression.Print(), GetType().Name)); @@ -283,7 +285,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional /// 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 @@ -295,7 +297,7 @@ protected override Expression VisitMember(MemberExpression memberExpression) { var expression = Visit(memberExpression.Expression); Expression updatedMemberExpression = memberExpression.Update( - expression != null ? MatchTypes(expression, memberExpression.Expression.Type) : expression); + expression != null ? MatchTypes(expression, memberExpression.Expression!.Type) : expression); if (expression?.Type.IsNullableValueType() == true) { @@ -320,7 +322,7 @@ 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; @@ -334,15 +336,15 @@ protected override Expression VisitMember(MemberExpression memberExpression) _projectionMembers.Push(projectionMember); visitedExpression = Visit(memberAssignment.Expression); - if (visitedExpression == null) + if (visitedExpression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return memberAssignment.Update(Expression.Convert(visitedExpression, memberAssignment.Expression.Type)); } _projectionMembers.Pop(); } - visitedExpression = MatchTypes(visitedExpression!, expression.Type); + visitedExpression = MatchTypes(visitedExpression, expression.Type); return memberAssignment.Update(visitedExpression); } @@ -353,14 +355,14 @@ 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 Expression? VisitMemberInit(MemberInitExpression memberInitExpression) + protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { Check.NotNull(memberInitExpression, nameof(memberInitExpression)); var newExpression = Visit(memberInitExpression.NewExpression); - if (newExpression == null) + if (newExpression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var newBindings = new MemberBinding[memberInitExpression.Bindings.Count]; @@ -368,13 +370,15 @@ protected override Expression VisitMember(MemberExpression memberExpression) { if (memberInitExpression.Bindings[i].BindingType != MemberBindingType.Assignment) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } newBindings[i] = VisitMemberBinding(memberInitExpression.Bindings[i]); - if (newBindings[i] == null) + if (((MemberAssignment)newBindings[i]).Expression is UnaryExpression unaryExpression + && unaryExpression.NodeType == ExpressionType.Convert + && unaryExpression.Operand == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } @@ -394,15 +398,15 @@ 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( - @object != null ? MatchTypes(@object, methodCallExpression.Object.Type) : @object, + @object != null ? MatchTypes(@object, methodCallExpression.Object!.Type) : @object!, arguments); if (@object?.Type.IsNullableType() == true - && !methodCallExpression.Object.Type.IsNullableType()) + && !methodCallExpression.Object!.Type.IsNullableType()) { var nullableReturnType = methodCallExpression.Type.MakeNullable(); if (!methodCallExpression.Type.IsNullableType()) @@ -425,7 +429,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)); @@ -437,7 +441,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (!_clientEval && newExpression.Members == null) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var newArguments = new Expression[newExpression.Arguments.Count]; @@ -451,18 +455,18 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } else { - var projectionMember = _projectionMembers.Peek().Append(newExpression.Members[i]); + var projectionMember = _projectionMembers.Peek().Append(newExpression.Members![i]); _projectionMembers.Push(projectionMember); visitedArgument = Visit(argument); - if (visitedArgument == null) + if (visitedArgument == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } _projectionMembers.Pop(); } - newArguments[i] = MatchTypes(visitedArgument!, argument.Type); + newArguments[i] = MatchTypes(visitedArgument, argument.Type); } return newExpression.Update(newArguments); @@ -475,7 +479,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp /// 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 @@ -485,7 +489,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.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index b0656bb5bd3..6d968e8ca77 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -14,6 +14,7 @@ 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 @@ -32,7 +33,7 @@ private static readonly ConstructorInfo _valueBufferConstructor = typeof(ValueBuffer).GetConstructors().Single(ci => ci.GetParameters().Length == 1); private static readonly PropertyInfo _valueBufferCountMemberInfo - = typeof(ValueBuffer).GetProperty(nameof(ValueBuffer.Count)); + = typeof(ValueBuffer).GetRequiredProperty(nameof(ValueBuffer.Count)); private readonly List _valueBufferSlots = new List(); @@ -248,8 +249,8 @@ public virtual int AddSubqueryProjection( var terminatingMethodCall = (MethodCallExpression)((LambdaExpression)((NewExpression)selectMethodCall.Arguments[0]).Arguments[0]).Body; selectMethodCall = selectMethodCall.Update( - null, new[] { terminatingMethodCall.Arguments[0], selectMethodCall.Arguments[1] }); - serverQueryExpression = terminatingMethodCall.Update(null, new[] { selectMethodCall }); + null!, new[] { terminatingMethodCall.Arguments[0], selectMethodCall.Arguments[1] }); + serverQueryExpression = terminatingMethodCall.Update(null!, new[] { selectMethodCall }); } innerShaper = new ShaperRemappingExpressionVisitor(subquery._projectionMapping) @@ -269,7 +270,8 @@ public ShaperRemappingExpressionVisitor(IDictionary expression is MethodCallExpression methodCallExpression && methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == ExpressionExtensions.ValueBufferTryReadValueMethod - ? (IPropertyBase)((ConstantExpression)methodCallExpression.Arguments[2]).Value + ? methodCallExpression.Arguments[2].GetConstantValue() : null; /// @@ -603,7 +605,7 @@ public virtual void AddInnerJoin( new Expression[] { outerParameter, innerParameter }); var index = 0; - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); + var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); foreach (var projection in _projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) @@ -627,7 +629,7 @@ public virtual void AddInnerJoin( } } - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); foreach (var projection in innerQueryExpression._projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) @@ -691,8 +693,8 @@ public virtual void AddLeftJoin( typeof(ValueBuffer), typeof(IEnumerable)); var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(IEnumerable), "inner"); - var outerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var innerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var outerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var innerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var resultSelector = Lambda( New( groupTransparentIdentifierType.GetTypeInfo().DeclaredConstructors.Single(), @@ -722,7 +724,7 @@ public virtual void AddLeftJoin( new Expression[] { MakeMemberAccess(outerParameter, outerMemberInfo), innerParameter }); var index = 0; - outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); + outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); foreach (var projection in _projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) @@ -748,7 +750,7 @@ public virtual void AddLeftJoin( } var outerIndex = index; - innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var nullableReadValueExpressionVisitor = new NullableReadValueExpressionVisitor(); foreach (var projection in innerQueryExpression._projectionMapping) { @@ -828,7 +830,7 @@ public virtual void AddSelectMany( new Expression[] { outerParameter, innerParameter }); var index = 0; - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); + var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); foreach (var projection in _projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) @@ -852,7 +854,7 @@ public virtual void AddSelectMany( } } - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var nullableReadValueExpressionVisitor = new NullableReadValueExpressionVisitor(); foreach (var projection in innerQueryExpression._projectionMapping) { @@ -927,8 +929,8 @@ public virtual EntityShaperExpression AddNavigationToWeakEntityType( typeof(ValueBuffer), typeof(IEnumerable)); var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(IEnumerable), "inner"); - var outerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var innerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var outerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var innerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var resultSelector = Lambda( New( groupTransparentIdentifierType.GetTypeInfo().DeclaredConstructors.Single(), @@ -1066,7 +1068,7 @@ EntityProjectionExpression CopyEntityProjectionToOuter(EntityProjectionExpressio static int GetValueBufferIndex(Expression expression) => expression is ConditionalExpression conditionalExpression ? GetValueBufferIndex(conditionalExpression.IfTrue) - : (int)((ConstantExpression)((MethodCallExpression)expression).Arguments[1]).Value; + : ((MethodCallExpression)expression).Arguments[1].GetConstantValue(); } /// diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index ac691d0d4da..edfd357bd8b 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -79,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 @@ -469,14 +469,15 @@ private static ShapedQueryExpression CreateShapedQueryExpressionStatic(IEntityTy 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]); - if (newArguments[i] == null) + var key = TranslateGroupingKey(newExpression.Arguments[i]); + if (key == null) { return null; } + newArguments[i] = key; } return newExpression.Update(newArguments); @@ -1053,9 +1054,9 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp Check.NotNull(source, nameof(source)); Check.NotNull(selector, nameof(selector)); - var innerParameter = Expression.Parameter(selector.ReturnType.TryGetSequenceType(), "i"); + var innerParameter = Expression.Parameter(selector.ReturnType.GetSequenceType(), "i"); var resultSelector = Expression.Lambda( - innerParameter, Expression.Parameter(source.Type.TryGetSequenceType()), innerParameter); + innerParameter, Expression.Parameter(source.Type.GetSequenceType()), innerParameter); return TranslateSelectMany(source, selector, resultSelector); } @@ -1339,7 +1340,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp source = Visit(source); return TryExpand(source, MemberIdentity.Create(navigationName)) - ?? methodCallExpression.Update(null, new[] { source, methodCallExpression.Arguments[1] }); + ?? methodCallExpression.Update(null!, new[] { source, methodCallExpression.Arguments[1] }); } if (methodCallExpression.TryGetEFPropertyArguments(out source, out navigationName)) @@ -1363,7 +1364,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)) @@ -1432,7 +1433,7 @@ protected override Expression VisitExtension(Expression extensionExpression) Expression.Equal(outerKey, innerKey)) : Expression.Equal(outerKey, innerKey); - var correlationPredicate = _expressionTranslator.Translate(predicate); + var correlationPredicate = _expressionTranslator.Translate(predicate)!; innerQueryExpression.UpdateServerQueryExpression( Expression.Call( EnumerableMethods.Where.MakeGenericMethod(innerQueryExpression.CurrentParameter.Type), @@ -1479,9 +1480,9 @@ protected override Expression VisitExtension(Expression extensionExpression) : foreignKey.Properties, makeNullable); - var outerKeySelector = Expression.Lambda(_expressionTranslator.Translate(outerKey), _queryExpression.CurrentParameter); + var outerKeySelector = Expression.Lambda(_expressionTranslator.Translate(outerKey)!, _queryExpression.CurrentParameter); var innerKeySelector = Expression.Lambda( - _expressionTranslator.Translate(innerKey), innerQueryExpression.CurrentParameter); + _expressionTranslator.Translate(innerKey)!, innerQueryExpression.CurrentParameter); (outerKeySelector, innerKeySelector) = AlignKeySelectorTypes(outerKeySelector, innerKeySelector); innerShaper = _queryExpression.AddNavigationToWeakEntityType( entityProjectionExpression, navigation, innerQueryExpression, outerKeySelector, innerKeySelector); diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs index 06206af6b05..2c999dd5c37 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.cs @@ -27,20 +27,16 @@ public CustomShaperCompilingExpressionVisitor(bool tracking) } private static readonly MethodInfo _includeReferenceMethodInfo - = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() - .GetDeclaredMethod(nameof(IncludeReference)); + = typeof(CustomShaperCompilingExpressionVisitor).GetRequiredDeclaredMethod(nameof(IncludeReference)); private static readonly MethodInfo _includeCollectionMethodInfo - = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() - .GetDeclaredMethod(nameof(IncludeCollection)); + = typeof(CustomShaperCompilingExpressionVisitor).GetRequiredDeclaredMethod(nameof(IncludeCollection)); private static readonly MethodInfo _materializeCollectionMethodInfo - = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() - .GetDeclaredMethod(nameof(MaterializeCollection)); + = typeof(CustomShaperCompilingExpressionVisitor).GetRequiredDeclaredMethod(nameof(MaterializeCollection)); private static readonly MethodInfo _materializeSingleResultMethodInfo - = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() - .GetDeclaredMethod(nameof(MaterializeSingleResult)); + = typeof(CustomShaperCompilingExpressionVisitor).GetRequiredDeclaredMethod(nameof(MaterializeSingleResult)); private static void IncludeReference( QueryContext queryContext, @@ -271,8 +267,7 @@ private static Expression AddToCollectionNavigation( Expression.Constant(true)); private static readonly MethodInfo _collectionAccessorAddMethodInfo - = typeof(IClrCollectionAccessor).GetTypeInfo() - .GetDeclaredMethod(nameof(IClrCollectionAccessor.Add)); + = typeof(IClrCollectionAccessor).GetRequiredDeclaredMethod(nameof(IClrCollectionAccessor.Add)); } } } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs index 4aa12a7672d..daeef79487c 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.InMemoryProjectionBindingRemovingExpressionVisitor.cs @@ -41,10 +41,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) = ((IDictionary)GetProjectionIndex(queryExpression, projectionBindingExpression), ((InMemoryQueryExpression)projectionBindingExpression.QueryExpression).CurrentParameter); - var updatedExpression = Expression.New( - newExpression.Constructor, - Expression.Constant(ValueBuffer.Empty), - newExpression.Arguments[1]); + var updatedExpression = newExpression.Update( + new[] { Expression.Constant(ValueBuffer.Empty), newExpression.Arguments[1] }); return Expression.MakeBinary(ExpressionType.Assign, binaryExpression.Left, updatedExpression); } @@ -67,10 +65,10 @@ 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 = methodCallExpression.Arguments[2].GetConstantValue(); var (indexMap, valueBuffer) = _materializationContextBindings[ - (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object]; + (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object!]; Check.DebugAssert( property != null || methodCallExpression.Type.IsNullableType(), "Must read nullable value without property"); @@ -113,7 +111,7 @@ protected override Expression VisitExtension(Expression extensionExpression) && methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericMethodDefinition() == ExpressionExtensions.ValueBufferTryReadValueMethod) { - return (IPropertyBase)((ConstantExpression)methodCallExpression.Arguments[2]).Value; + return methodCallExpression.Arguments[2].GetConstantValue(); } return null; @@ -124,7 +122,7 @@ private object GetProjectionIndex( ProjectionBindingExpression projectionBindingExpression) { return projectionBindingExpression.ProjectionMember != null - ? ((ConstantExpression)queryExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value + ? queryExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember).GetConstantValue() : (projectionBindingExpression.Index != null ? (object)projectionBindingExpression.Index : projectionBindingExpression.IndexMap!); diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs index bf27e11648d..3165dcc2bf0 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.cs @@ -97,8 +97,7 @@ protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQuery } private static readonly MethodInfo _tableMethodInfo - = typeof(InMemoryShapedQueryCompilingExpressionVisitor).GetTypeInfo() - .GetDeclaredMethod(nameof(Table)); + = typeof(InMemoryShapedQueryCompilingExpressionVisitor).GetRequiredDeclaredMethod(nameof(Table)); private static IEnumerable Table( QueryContext queryContext, diff --git a/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs index 435273fec98..822294fa19a 100644 --- a/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs @@ -78,7 +78,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var key = GenerateKey((ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression); if (!_mapping.TryGetValue(key, out var variable)) { - variable = Expression.Parameter(entityShaperExpression.EntityType.ClrType); + variable = Expression.Parameter(entityShaperExpression.EntityType.ClrType!); _variables.Add(variable); _expressions.Add(Expression.Assign(variable, entityShaperExpression)); _mapping[key] = variable; diff --git a/src/EFCore.Proxies/EFCore.Proxies.csproj b/src/EFCore.Proxies/EFCore.Proxies.csproj index 9b51b9990bb..c2b173a670b 100644 --- a/src/EFCore.Proxies/EFCore.Proxies.csproj +++ b/src/EFCore.Proxies/EFCore.Proxies.csproj @@ -2,7 +2,7 @@ Lazy-loading proxies for Entity Framework Core. - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.Proxies Microsoft.EntityFrameworkCore diff --git a/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs b/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs index 68f7fd92017..6baa6d733c9 100644 --- a/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs @@ -247,7 +247,7 @@ public virtual Task TransactionCommittedAsync( => Task.CompletedTask; /// - /// Called just before EF intends to call . + /// Called just before EF intends to call . /// /// The transaction. /// Contextual information about connection and transaction. @@ -271,7 +271,7 @@ public virtual InterceptionResult TransactionRollingBack( => result; /// - /// Called immediately after EF calls . + /// Called immediately after EF calls . /// /// The transaction. /// Contextual information about connection and transaction. @@ -309,7 +309,7 @@ public virtual ValueTask TransactionRollingBackAsync( => new ValueTask(result); /// - /// Called immediately after EF calls . + /// Called immediately after EF calls . /// /// The transaction. /// Contextual information about connection and transaction. diff --git a/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs b/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs index 7c15aa510b0..8fc07bc591c 100644 --- a/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs @@ -252,7 +252,7 @@ Task TransactionCommittedAsync( CancellationToken cancellationToken = default); /// - /// Called just before EF intends to call . + /// Called just before EF intends to call . /// /// The transaction. /// Contextual information about connection and transaction. @@ -275,7 +275,7 @@ InterceptionResult TransactionRollingBack( InterceptionResult result); /// - /// Called immediately after EF calls . + /// Called immediately after EF calls . /// /// The transaction. /// Contextual information about connection and transaction. @@ -310,7 +310,7 @@ ValueTask TransactionRollingBackAsync( CancellationToken cancellationToken = default); /// - /// Called immediately after EF calls . + /// Called immediately after EF calls . /// /// The transaction. /// Contextual information about connection and transaction. diff --git a/src/EFCore.Relational/EFCore.Relational.csproj b/src/EFCore.Relational/EFCore.Relational.csproj index 31eb1579fb3..63f762afe0a 100644 --- a/src/EFCore.Relational/EFCore.Relational.csproj +++ b/src/EFCore.Relational/EFCore.Relational.csproj @@ -2,7 +2,7 @@ Shared Entity Framework Core components for relational database providers. - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.Relational Microsoft.EntityFrameworkCore diff --git a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs index a90a85aa9a8..145e6a52e7b 100644 --- a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs @@ -151,7 +151,7 @@ public static IQueryable FromSqlInterpolated( private static FromSqlQueryRootExpression GenerateFromSqlQueryRoot( IQueryable source, string sql, - object[] arguments, + object?[] arguments, [CallerMemberName] string memberName = null!) { var queryRootExpression = (QueryRootExpression)source.Expression; @@ -200,7 +200,7 @@ public static IQueryable AsSingleQuery( } internal static readonly MethodInfo AsSingleQueryMethodInfo - = typeof(RelationalQueryableExtensions).GetTypeInfo().GetDeclaredMethod(nameof(AsSingleQuery)); + = typeof(RelationalQueryableExtensions).GetRequiredDeclaredMethod(nameof(AsSingleQuery)); /// /// @@ -233,6 +233,6 @@ public static IQueryable AsSplitQuery( } internal static readonly MethodInfo AsSplitQueryMethodInfo - = typeof(RelationalQueryableExtensions).GetTypeInfo().GetDeclaredMethod(nameof(AsSplitQuery)); + = typeof(RelationalQueryableExtensions).GetRequiredDeclaredMethod(nameof(AsSplitQuery)); } } diff --git a/src/EFCore.Relational/Query/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs index d61e44280c6..0f60fd620a6 100644 --- a/src/EFCore.Relational/Query/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -96,7 +96,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) propertyExpressionMap[expression.Key] = newExpression; } - var discriminatorExpression = (SqlExpression)visitor.Visit(DiscriminatorExpression); + var discriminatorExpression = (SqlExpression?)visitor.Visit(DiscriminatorExpression); changed |= discriminatorExpression != DiscriminatorExpression; return changed @@ -152,7 +152,7 @@ public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType { var entityTypesToSelect = derivedType.GetTptDiscriminatorValues(); var whenClauses = caseExpression.WhenClauses - .Where(wc => entityTypesToSelect.Contains((string)((SqlConstantExpression)wc.Result).Value)) + .Where(wc => entityTypesToSelect.Contains((string)((SqlConstantExpression)wc.Result).Value!)) .ToList(); discriminatorExpression = caseExpression.Update(operand: null, whenClauses, elseResult: null); diff --git a/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs b/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs index 4dbc054c7ba..fa736924795 100644 --- a/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs +++ b/src/EFCore.Relational/Query/Internal/BufferedDataReader.cs @@ -326,7 +326,7 @@ public override byte GetByte(int ordinal) /// 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 long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) + public override long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length) { throw new NotSupportedException(); } @@ -349,7 +349,7 @@ public override char GetChar(int ordinal) /// 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 long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) + public override long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length) { throw new NotSupportedException(); } diff --git a/src/EFCore.Relational/Query/Internal/CollateTranslator.cs b/src/EFCore.Relational/Query/Internal/CollateTranslator.cs index f43a3f6cb44..4f3ff2e0953 100644 --- a/src/EFCore.Relational/Query/Internal/CollateTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/CollateTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -20,7 +21,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal public class CollateTranslator : IMethodCallTranslator { private static readonly MethodInfo _methodInfo - = typeof(RelationalDbFunctionsExtensions).GetMethod(nameof(RelationalDbFunctionsExtensions.Collate)); + = typeof(RelationalDbFunctionsExtensions).GetRequiredMethod(nameof(RelationalDbFunctionsExtensions.Collate)); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs index a382c5f3e56..321addb22aa 100644 --- a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs @@ -22,7 +22,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal public class EnumHasFlagTranslator : IMethodCallTranslator { private static readonly MethodInfo _methodInfo - = typeof(Enum).GetRuntimeMethod(nameof(Enum.HasFlag), new[] { typeof(Enum) }); + = typeof(Enum).GetRequiredRuntimeMethod(nameof(Enum.HasFlag), new[] { typeof(Enum) }); private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs index 71bcc951e79..d36d2774288 100644 --- a/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlParameterExpandingExpressionVisitor.cs @@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -31,7 +32,7 @@ private readonly IDictionary _visitedFromSqlExpre private readonly IRelationalTypeMappingSource _typeMappingSource; private readonly IParameterNameGeneratorFactory _parameterNameGeneratorFactory; - private IReadOnlyDictionary _parametersValues; + private IReadOnlyDictionary _parametersValues; private ParameterNameGenerator _parameterNameGenerator; private bool _canCache; @@ -61,7 +62,7 @@ public FromSqlParameterExpandingExpressionVisitor( /// public virtual SelectExpression Expand( [NotNull] SelectExpression selectExpression, - [NotNull] IReadOnlyDictionary parameterValues, + [NotNull] IReadOnlyDictionary parameterValues, out bool canCache) { Check.NotNull(selectExpression, nameof(selectExpression)); @@ -84,7 +85,8 @@ public virtual SelectExpression Expand( /// 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) { if (expression is FromSqlExpression fromSql) { @@ -93,7 +95,8 @@ public override Expression Visit(Expression expression) switch (fromSql.Arguments) { case ParameterExpression parameterExpression: - var parameterValues = (object[])_parametersValues[parameterExpression.Name]; + // parameter value will never be null. It could be empty object[] + var parameterValues = (object[])_parametersValues[parameterExpression.Name!]!; _canCache = false; var subParameters = new List(parameterValues.Length); @@ -132,8 +135,8 @@ public override Expression Visit(Expression expression) break; case ConstantExpression constantExpression: - var existingValues = (object[])constantExpression.Value; - var constantValues = new object[existingValues.Length]; + var existingValues = constantExpression.GetConstantValue(); + var constantValues = new object?[existingValues.Length]; for (var i = 0; i < existingValues.Length; i++) { var value = existingValues[i]; @@ -158,10 +161,14 @@ public override Expression Visit(Expression expression) } } - updatedFromSql = fromSql.Update(Expression.Constant(constantValues, typeof(object[]))); + updatedFromSql = fromSql.Update(Expression.Constant(constantValues, typeof(object?[]))); _visitedFromSqlExpressions[fromSql] = updatedFromSql; break; + + default: + Check.DebugAssert(false, "FromSql.Arguments must be Constant/ParameterExpression"); + break; } } diff --git a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs index b305e31480a..cc4084713fa 100644 --- a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -21,12 +22,12 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal public class LikeTranslator : IMethodCallTranslator { private static readonly MethodInfo _methodInfo - = typeof(DbFunctionsExtensions).GetRuntimeMethod( + = typeof(DbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), typeof(string), typeof(string) }); private static readonly MethodInfo _methodInfoWithEscape - = typeof(DbFunctionsExtensions).GetRuntimeMethod( + = typeof(DbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), typeof(string), typeof(string), typeof(string) }); diff --git a/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs b/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs index aed293011ec..2e5d0522177 100644 --- a/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/NullableMemberTranslator.cs @@ -49,7 +49,7 @@ public NullableMemberTranslator([NotNull] ISqlExpressionFactory sqlExpressionFac Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); - if (member.DeclaringType.IsNullableValueType() + if (member.DeclaringType?.IsNullableValueType() == true && instance != null) { switch (member.Name) diff --git a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs index ae1fbb89cef..9b4cba950d5 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs @@ -65,7 +65,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 IRelationalCommand GetRelationalCommand([NotNull] IReadOnlyDictionary parameters) + public virtual IRelationalCommand GetRelationalCommand([NotNull] IReadOnlyDictionary parameters) { var cacheKey = new CommandCacheKey(_selectExpression, parameters); @@ -123,9 +123,9 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) private readonly struct CommandCacheKey : IEquatable { private readonly SelectExpression _selectExpression; - private readonly IReadOnlyDictionary _parameterValues; + private readonly IReadOnlyDictionary _parameterValues; - public CommandCacheKey(SelectExpression selectExpression, IReadOnlyDictionary parameterValues) + public CommandCacheKey(SelectExpression selectExpression, IReadOnlyDictionary parameterValues) { _selectExpression = selectExpression; _parameterValues = parameterValues; diff --git a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs index 416b1f9b130..b922e67fe0c 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs @@ -13,6 +13,7 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -27,8 +28,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal public class RelationalProjectionBindingExpressionVisitor : ExpressionVisitor { private static readonly MethodInfo _getParameterValueMethodInfo - = typeof(RelationalProjectionBindingExpressionVisitor) - .GetTypeInfo().GetDeclaredMethod(nameof(GetParameterValue)); + = typeof(RelationalProjectionBindingExpressionVisitor).GetRequiredDeclaredMethod(nameof(GetParameterValue)); private readonly RelationalQueryableMethodTranslatingExpressionVisitor _queryableMethodTranslatingExpressionVisitor; private readonly RelationalSqlTranslatingExpressionVisitor _sqlTranslator; @@ -76,7 +76,7 @@ public virtual Expression Translate([NotNull] SelectExpression selectExpression, var expandedExpression = _queryableMethodTranslatingExpressionVisitor.ExpandWeakEntities(_selectExpression, expression); var result = Visit(expandedExpression); - if (result == null) + if (result == QueryCompilationContext.NotTranslatedExpression) { _clientEval = true; @@ -104,6 +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. /// + [return: CA.NotNullIfNotNull("expression")] public override Expression? Visit(Expression? expression) { if (expression == null) @@ -168,7 +169,7 @@ public virtual Expression Translate([NotNull] SelectExpression selectExpression, _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( materializeCollectionNavigationExpression.Subquery)!, materializeCollectionNavigationExpression.Navigation, - materializeCollectionNavigationExpression.Navigation.ClrType.TryGetSequenceType()!); + materializeCollectionNavigationExpression.Navigation.ClrType.GetSequenceType()); case MethodCallExpression methodCallExpression: { @@ -240,7 +241,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) var translation = _sqlTranslator.Translate(expression); if (translation == null) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } _projectionMapping[_projectionMembers.Peek()] = translation; @@ -260,8 +261,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); } @@ -274,9 +275,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?)) { @@ -292,7 +293,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)); @@ -319,7 +320,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional return entityShaperExpression.Update(new ProjectionBindingExpression(_selectExpression, indexMap)); } - return null; + return QueryCompilationContext.NotTranslatedExpression; } entityProjectionExpression = (EntityProjectionExpression)((SelectExpression)projectionBindingExpression.QueryExpression) @@ -344,10 +345,10 @@ protected override Expression VisitConditional(ConditionalExpression conditional } case IncludeExpression _: - return _clientEval ? base.VisitExtension(extensionExpression) : null; + return _clientEval ? base.VisitExtension(extensionExpression) : QueryCompilationContext.NotTranslatedExpression; case CollectionShaperExpression _: - return _clientEval ? extensionExpression : null; + return _clientEval ? extensionExpression : QueryCompilationContext.NotTranslatedExpression; default: throw new InvalidOperationException(CoreStrings.QueryFailed(extensionExpression.Print(), GetType().Name)); @@ -373,7 +374,7 @@ protected override Expression VisitMember(MemberExpression memberExpression) { var expression = Visit(memberExpression.Expression); Expression updatedMemberExpression = memberExpression.Update( - expression != null ? MatchTypes(expression, memberExpression.Expression.Type) : expression); + expression != null ? MatchTypes(expression, memberExpression.Expression!.Type) : expression); if (expression?.Type.IsNullableType() == true && !_includeFindingExpressionVisitor.ContainsInclude(expression)) @@ -399,7 +400,7 @@ 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; @@ -413,15 +414,15 @@ protected override Expression VisitMember(MemberExpression memberExpression) _projectionMembers.Push(projectionMember); visitedExpression = Visit(memberAssignment.Expression); - if (visitedExpression == null) + if (visitedExpression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return memberAssignment.Update(Expression.Convert(visitedExpression, expression.Type)); } _projectionMembers.Pop(); } - visitedExpression = MatchTypes(visitedExpression!, expression.Type); + visitedExpression = MatchTypes(visitedExpression, expression.Type); return memberAssignment.Update(visitedExpression); } @@ -432,14 +433,14 @@ 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 Expression? VisitMemberInit(MemberInitExpression memberInitExpression) + protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { Check.NotNull(memberInitExpression, nameof(memberInitExpression)); var newExpression = Visit(memberInitExpression.NewExpression); - if (newExpression == null) + if (newExpression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var newBindings = new MemberBinding[memberInitExpression.Bindings.Count]; @@ -447,14 +448,16 @@ protected override Expression VisitMember(MemberExpression memberExpression) { if (memberInitExpression.Bindings[i].BindingType != MemberBindingType.Assignment) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } newBindings[i] = VisitMemberBinding(memberInitExpression.Bindings[i]); - - if (newBindings[i] == null) + if (newBindings[i] is MemberAssignment memberAssignment + && memberAssignment.Expression is UnaryExpression unaryExpression + && unaryExpression.NodeType == ExpressionType.Convert + && unaryExpression.Operand == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } @@ -478,10 +481,11 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } Expression updatedMethodCallExpression = methodCallExpression.Update( - @object != null ? MatchTypes(@object, methodCallExpression.Object.Type) : @object, + @object != null ? MatchTypes(@object, methodCallExpression.Object!.Type) : @object!, arguments); if (@object?.Type.IsNullableType() == true + && methodCallExpression.Object != null && !methodCallExpression.Object.Type.IsNullableType()) { var nullableReturnType = methodCallExpression.Type.MakeNullable(); @@ -505,7 +509,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)); @@ -517,7 +521,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (!_clientEval && newExpression.Members == null) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var newArguments = new Expression[newExpression.Arguments.Count]; @@ -531,12 +535,12 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp } else { - var projectionMember = _projectionMembers.Peek().Append(newExpression.Members[i]); + var projectionMember = _projectionMembers.Peek().Append(newExpression.Members![i]); _projectionMembers.Push(projectionMember); visitedArgument = Visit(argument); - if (visitedArgument == null) + if (visitedArgument == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } _projectionMembers.Pop(); @@ -590,7 +594,7 @@ private static Expression MatchTypes(Expression expression, Type targetType) #pragma warning disable IDE0052 // Remove unread private members private static T GetParameterValue(QueryContext queryContext, string parameterName) #pragma warning restore IDE0052 // Remove unread private members - => (T)queryContext.ParameterValues[parameterName]; + => (T)queryContext.ParameterValues[parameterName]!; private sealed class IncludeFindingExpressionVisitor : ExpressionVisitor { @@ -605,7 +609,8 @@ public bool ContainsInclude(Expression expression) return _containsInclude; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) => _containsInclude ? expression : base.Visit(expression); protected override Expression VisitExtension(Expression extensionExpression) diff --git a/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs index b2848ef93a1..f680c0aec6c 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalValueConverterCompensatingExpressionVisitor.cs @@ -6,6 +6,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -63,7 +64,7 @@ private Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryE private Expression VisitCase(CaseExpression caseExpression) { var testIsCondition = caseExpression.Operand == null; - var operand = (SqlExpression)Visit(caseExpression.Operand); + var operand = (SqlExpression?)Visit(caseExpression.Operand); var whenClauses = new List(); foreach (var whenClause in caseExpression.WhenClauses) { @@ -77,7 +78,7 @@ private Expression VisitCase(CaseExpression caseExpression) whenClauses.Add(new CaseWhenClause(test, result)); } - var elseResult = (SqlExpression)Visit(caseExpression.ElseResult); + var elseResult = (SqlExpression?)Visit(caseExpression.ElseResult); return caseExpression.Update(operand, whenClauses, elseResult); } @@ -101,7 +102,7 @@ private Expression VisitSelect(SelectExpression selectExpression) tables.Add(newTable); } - var predicate = TryCompensateForBoolWithValueConverter((SqlExpression)Visit(selectExpression.Predicate)); + var predicate = TryCompensateForBoolWithValueConverter((SqlExpression?)Visit(selectExpression.Predicate)); changed |= predicate != selectExpression.Predicate; var groupBy = new List(); @@ -112,7 +113,7 @@ private Expression VisitSelect(SelectExpression selectExpression) groupBy.Add(newGroupingKey); } - var having = TryCompensateForBoolWithValueConverter((SqlExpression)Visit(selectExpression.Having)); + var having = TryCompensateForBoolWithValueConverter((SqlExpression?)Visit(selectExpression.Having)); changed |= having != selectExpression.Having; var orderings = new List(); @@ -123,10 +124,10 @@ private Expression VisitSelect(SelectExpression selectExpression) orderings.Add(ordering.Update(orderingExpression)); } - var offset = (SqlExpression)Visit(selectExpression.Offset); + var offset = (SqlExpression?)Visit(selectExpression.Offset); changed |= offset != selectExpression.Offset; - var limit = (SqlExpression)Visit(selectExpression.Limit); + var limit = (SqlExpression?)Visit(selectExpression.Limit); changed |= limit != selectExpression.Limit; return changed @@ -151,7 +152,8 @@ private Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression) return leftJoinExpression.Update(table, joinPredicate); } - private SqlExpression TryCompensateForBoolWithValueConverter(SqlExpression sqlExpression) + [return: CA.NotNullIfNotNull("sqlExpression")] + private SqlExpression? TryCompensateForBoolWithValueConverter(SqlExpression? sqlExpression) { if (sqlExpression is ColumnExpression columnExpression && columnExpression.TypeMapping!.ClrType == typeof(bool) diff --git a/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs index d51ac64462e..5c5271423bd 100644 --- a/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SplitIncludeRewritingExpressionVisitor.cs @@ -55,12 +55,12 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp reverseOrdering); source = selectMethodCall.Update( - selectMethodCall.Object, + selectMethodCall.Object!, new[] { selectMethodCall.Arguments[0], Expression.Quote(selector) }); if (singleResult) { - source = methodCallExpression.Update(methodCallExpression.Object, new[] { source }); + source = methodCallExpression.Update(methodCallExpression.Object!, new[] { source }); } return source; @@ -78,7 +78,7 @@ private LambdaExpression RewriteCollectionInclude( { var selectorParameter = selector.Parameters[0]; var selectorBody = selector.Body; - var sourceElementType = source.Type.TryGetSequenceType()!; + var sourceElementType = source.Type.GetSequenceType(); if (reverseOrdering) { @@ -132,7 +132,7 @@ protected override Expression VisitExtension(Expression extensionExpression) && subqueryMethodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.Select) { subquery = RewriteSubqueryToSelectMany(subqueryMethodCallExpression.Arguments[0]); - subquery = subqueryMethodCallExpression.Update(null, new[] { subquery, subqueryMethodCallExpression.Arguments[1] }); + subquery = subqueryMethodCallExpression.Update(null!, new[] { subquery, subqueryMethodCallExpression.Arguments[1] }); subquery = _parentVisitor.Visit(subquery); } else @@ -148,7 +148,7 @@ protected override Expression VisitExtension(Expression extensionExpression) private Expression RewriteSubqueryToSelectMany(Expression subquery) { - var collectionElementType = subquery.Type.TryGetSequenceType(); + var collectionElementType = subquery.Type.GetSequenceType(); if (subquery.Type.GetGenericTypeDefinition() == typeof(IOrderedQueryable<>)) { subquery = Expression.Call( @@ -180,7 +180,8 @@ protected override Expression VisitLambda(Expression lambdaExpression) var newParameters = CopyParameters(lambdaExpression.Parameters); body = new ReplacingExpressionVisitor(lambdaExpression.Parameters, newParameters).Visit(body); - return lambdaExpression.Update(body, newParameters); + // TODO-Nullable bug + return lambdaExpression.Update(body, newParameters)!; } private static IReadOnlyList CopyParameters(IReadOnlyList parameters) diff --git a/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs index a759673ff8d..48b2cff9b07 100644 --- a/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SqlExpressionOptimizingExpressionVisitor.cs @@ -395,16 +395,16 @@ private SqlExpression SimplifyBinaryExpression( typeMapping); } - var leftBoolConstant = left.Type == typeof(bool) ? leftConstant : null; - var rightBoolConstant = right.Type == typeof(bool) ? rightConstant : null; - if (leftBoolConstant != null || rightBoolConstant != null) + var leftBoolValue = left.Type == typeof(bool) ? (bool?)leftConstant?.Value : null; + var rightBoolValue = right.Type == typeof(bool) ? (bool?)rightConstant?.Value : null; + if (leftBoolValue != null || rightBoolValue != null) { return SimplifyBoolConstantComparisonExpression( operatorType, left, right, - leftBoolConstant, - rightBoolConstant, + leftBoolValue, + rightBoolValue, typeMapping); } @@ -458,18 +458,18 @@ private SqlExpression SimplifyBoolConstantComparisonExpression( ExpressionType operatorType, SqlExpression left, SqlExpression right, - SqlConstantExpression? leftBoolConstant, - SqlConstantExpression? rightBoolConstant, + bool? leftBoolValue, + bool? rightBoolValue, RelationalTypeMapping typeMapping) { - if (leftBoolConstant != null && rightBoolConstant != null) + if (leftBoolValue != null && rightBoolValue != null) { return operatorType == ExpressionType.Equal - ? _sqlExpressionFactory.Constant((bool)leftBoolConstant.Value == (bool)rightBoolConstant.Value, typeMapping) - : _sqlExpressionFactory.Constant((bool)leftBoolConstant.Value != (bool)rightBoolConstant.Value, typeMapping); + ? _sqlExpressionFactory.Constant(leftBoolValue.Value == rightBoolValue.Value, typeMapping) + : _sqlExpressionFactory.Constant(leftBoolValue.Value != rightBoolValue.Value, typeMapping); } - if (rightBoolConstant != null + if (rightBoolValue != null && CanOptimize(left)) { // a == true -> a @@ -478,15 +478,15 @@ private SqlExpression SimplifyBoolConstantComparisonExpression( // a != false -> a // only correct when f(x) can't be null return operatorType == ExpressionType.Equal - ? (bool)rightBoolConstant.Value + ? rightBoolValue.Value ? left : SimplifyUnaryExpression(ExpressionType.Not, left, typeof(bool), typeMapping) - : (bool)rightBoolConstant.Value + : rightBoolValue.Value ? SimplifyUnaryExpression(ExpressionType.Not, left, typeof(bool), typeMapping) : left; } - if (leftBoolConstant != null + if (leftBoolValue != null && CanOptimize(right)) { // true == a -> a @@ -495,10 +495,10 @@ private SqlExpression SimplifyBoolConstantComparisonExpression( // false != a -> a // only correct when a can't be null return operatorType == ExpressionType.Equal - ? (bool)leftBoolConstant.Value + ? leftBoolValue.Value ? right : SimplifyUnaryExpression(ExpressionType.Not, right, typeof(bool), typeMapping) - : (bool)leftBoolConstant.Value + : leftBoolValue.Value ? SimplifyUnaryExpression(ExpressionType.Not, right, typeof(bool), typeMapping) : right; } @@ -524,28 +524,30 @@ private SqlExpression SimplifyLogicalSqlBinaryExpression( // true || a -> true // false && a -> false // false || a -> a - if (left is SqlConstantExpression newLeftConstant) + if (left is SqlConstantExpression newLeftConstant + && newLeftConstant.Value is bool leftBoolValue) { return operatorType == ExpressionType.AndAlso - ? (bool)newLeftConstant.Value + ? leftBoolValue ? right : newLeftConstant - : (bool)newLeftConstant.Value + : leftBoolValue ? newLeftConstant : right; } - if (right is SqlConstantExpression newRightConstant) + if (right is SqlConstantExpression newRightConstant + && newRightConstant.Value is bool rightBoolValue) { // a && true -> a // a || true -> true // a && false -> false // a || false -> a return operatorType == ExpressionType.AndAlso - ? (bool)newRightConstant.Value + ? rightBoolValue ? left : newRightConstant - : (bool)newRightConstant.Value + : rightBoolValue ? newRightConstant : left; } diff --git a/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs index a2b71fb6f22..c9658136d27 100644 --- a/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs @@ -83,7 +83,7 @@ private bool IsCompareTo([CA.NotNullWhen(true)] CaseExpression? caseExpression) && constant.Value is int)) { var whenClauses = caseExpression.WhenClauses.Select( - c => new { test = (SqlBinaryExpression)c.Test, resultValue = (int)((SqlConstantExpression)c.Result).Value }).ToList(); + c => new { test = (SqlBinaryExpression)c.Test, resultValue = (int)((SqlConstantExpression)c.Result).Value! }).ToList(); if (whenClauses[0].test.Left.Equals(whenClauses[1].test.Left) && whenClauses[1].test.Left.Equals(whenClauses[2].test.Left) @@ -394,12 +394,12 @@ private bool TryGetInExressionCandidateInfo( && (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) { - candidateInfo = (column, constant.Value, constant.TypeMapping!, sqlBinaryExpression.OperatorType); + candidateInfo = (column, constant.Value!, constant.TypeMapping!, sqlBinaryExpression.OperatorType); return true; } } @@ -408,7 +408,7 @@ private bool TryGetInExressionCandidateInfo( && inExpression.Subquery == null && inExpression.Values is SqlConstantExpression valuesConstant) { - candidateInfo = (column, valuesConstant.Value, valuesConstant.TypeMapping!, + candidateInfo = (column, valuesConstant.Value!, valuesConstant.TypeMapping!, inExpression.IsNegated ? ExpressionType.NotEqual : ExpressionType.Equal); return true; diff --git a/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs b/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs index bc92d47d664..5aa9d12571a 100644 --- a/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/StringMethodTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -21,10 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal public class StringMethodTranslator : IMethodCallTranslator { private static readonly MethodInfo _isNullOrEmptyMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.IsNullOrEmpty), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IsNullOrEmpty), new[] { typeof(string) }); private static readonly MethodInfo _concatMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) }); private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs index 7a7240e3c0d..7973b4e1dc6 100644 --- a/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/TableAliasUniquifyingExpressionVisitor.cs @@ -58,7 +58,8 @@ private sealed class ScopedVisitor : ExpressionVisitor private readonly ISet _visitedTableExpressionBases = new HashSet(LegacyReferenceEqualityComparer.Instance); - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { var visitedExpression = base.Visit(expression); if (visitedExpression is TableExpressionBase tableExpressionBase diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index 6f8a7f60249..9f159d7752b 100644 --- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -803,7 +803,7 @@ protected override Expression VisitIn(InExpression inExpression) _relationalCommandBuilder.Append(inExpression.IsNegated ? " NOT IN " : " IN "); _relationalCommandBuilder.Append("("); var valuesConstant = (SqlConstantExpression)inExpression.Values; - var valuesList = ((IEnumerable)valuesConstant.Value) + var valuesList = ((IEnumerable)valuesConstant.Value!) .Select(v => new SqlConstantExpression(Expression.Constant(v), valuesConstant.TypeMapping)).ToList(); GenerateList(valuesList, e => Visit(e)); _relationalCommandBuilder.Append(")"); diff --git a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs index 6048f2d7ee5..f9c132026f4 100644 --- a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs +++ b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessor.cs @@ -56,7 +56,7 @@ public RelationalParameterBasedSqlProcessor( /// An optimized select expression. public virtual SelectExpression Optimize( [NotNull] SelectExpression selectExpression, - [NotNull] IReadOnlyDictionary parametersValues, + [NotNull] IReadOnlyDictionary parametersValues, out bool canCache) { Check.NotNull(selectExpression, nameof(selectExpression)); @@ -82,7 +82,7 @@ public virtual SelectExpression Optimize( /// A processed select expression. protected virtual SelectExpression ProcessSqlNullability( [NotNull] SelectExpression selectExpression, - [NotNull] IReadOnlyDictionary parametersValues, + [NotNull] IReadOnlyDictionary parametersValues, out bool canCache) { Check.NotNull(selectExpression, nameof(selectExpression)); @@ -100,7 +100,7 @@ protected virtual SelectExpression ProcessSqlNullability( /// A processed select expression. protected virtual SelectExpression ExpandFromSqlParameter( [NotNull] SelectExpression selectExpression, - [NotNull] IReadOnlyDictionary parametersValues, + [NotNull] IReadOnlyDictionary parametersValues, out bool canCache) { Check.NotNull(selectExpression, nameof(selectExpression)); diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 5cf720ed993..7dac5213d7d 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -82,7 +82,7 @@ protected RelationalQueryableMethodTranslatingExpressionVisitor( } /// - protected override Expression? VisitExtension(Expression extensionExpression) + protected override Expression VisitExtension(Expression extensionExpression) { switch (extensionExpression) { @@ -92,7 +92,7 @@ protected RelationalQueryableMethodTranslatingExpressionVisitor( _sqlExpressionFactory.Select( fromSqlQueryRootExpression.EntityType, new FromSqlExpression( - fromSqlQueryRootExpression.EntityType.GetDefaultMappings().SingleOrDefault().Table.Name.Substring(0, 1) + fromSqlQueryRootExpression.EntityType.GetDefaultMappings().Single().Table.Name.Substring(0, 1) .ToLowerInvariant(), fromSqlQueryRootExpression.Sql, fromSqlQueryRootExpression.Argument))); @@ -110,7 +110,8 @@ protected RelationalQueryableMethodTranslatingExpressionVisitor( if (methodInfo != null) { var methodCall = Expression.Call( - Expression.Constant(null, methodInfo.DeclaringType), + // Declaring types would be derived db context. + Expression.Constant(null, methodInfo.DeclaringType!), methodInfo, tableValuedFunctionQueryRootExpression.Arguments); @@ -504,14 +505,16 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent 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]); - if (newArguments[i] == null) + var key = TranslateGroupingKey(newExpression.Arguments[i]); + if (key == null) { return null; } + + newArguments[i] = key; } return newExpression.Update(newArguments); @@ -1026,9 +1029,9 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp Check.NotNull(source, nameof(source)); Check.NotNull(selector, nameof(selector)); - var innerParameter = Expression.Parameter(selector.ReturnType.TryGetSequenceType(), "i"); + var innerParameter = Expression.Parameter(selector.ReturnType.GetSequenceType(), "i"); var resultSelector = Expression.Lambda( - innerParameter, Expression.Parameter(source.Type.TryGetSequenceType()), innerParameter); + innerParameter, Expression.Parameter(source.Type.GetSequenceType()), innerParameter); return TranslateSelectMany(source, selector, resultSelector); } @@ -1272,7 +1275,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp source = Visit(source); return TryExpand(source, MemberIdentity.Create(navigationName)) - ?? methodCallExpression.Update(null, new[] { source, methodCallExpression.Arguments[1] }); + ?? methodCallExpression.Update(null!, new[] { source, methodCallExpression.Arguments[1] }); } if (methodCallExpression.TryGetEFPropertyArguments(out source, out navigationName)) @@ -1296,7 +1299,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)) @@ -1344,7 +1347,7 @@ protected override Expression VisitExtension(Expression extensionExpression) .Select(p => p.ClrType) .Any(t => t.IsNullableType()); - var innerSequenceType = innerShapedQuery.Type.TryGetSequenceType(); + var innerSequenceType = innerShapedQuery.Type.GetSequenceType(); var correlationPredicateParameter = Expression.Parameter(innerSequenceType); var outerKey = entityShaperExpression.CreateKeyValuesExpression( @@ -1490,7 +1493,7 @@ protected override Expression VisitExtension(Expression extensionExpression) if (identifyingColumn.Table is SelectExpression subquery) { var subqueryIdentifyingColumn = (ColumnExpression)subquery.Projection - .SingleOrDefault(e => string.Equals(e.Alias, identifyingColumn.Name, StringComparison.OrdinalIgnoreCase)) + .Single(e => string.Equals(e.Alias, identifyingColumn.Name, StringComparison.OrdinalIgnoreCase)) .Expression; var subqueryPropertyExpressions = GetPropertyExpressionFromSameTable( @@ -1553,7 +1556,7 @@ private static Expression AccessField( Type transparentIdentifierType, Expression targetExpression, string fieldName) - => Expression.Field(targetExpression, transparentIdentifierType.GetTypeInfo().GetDeclaredField(fieldName)); + => Expression.Field(targetExpression, transparentIdentifierType.GetRequiredDeclaredField(fieldName)); private static void HandleGroupByForAggregate(SelectExpression selectExpression, bool eraseProjection = false) { diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index 41a768e3a29..af7f47637be 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -19,6 +19,7 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -30,13 +31,13 @@ private sealed class ShaperProcessingExpressionVisitor : ExpressionVisitor { // Reading database values private static readonly MethodInfo _isDbNullMethod = - typeof(DbDataReader).GetRuntimeMethod(nameof(DbDataReader.IsDBNull), new[] { typeof(int) }); + typeof(DbDataReader).GetRequiredRuntimeMethod(nameof(DbDataReader.IsDBNull), new[] { typeof(int) }); private static readonly MethodInfo _getFieldValueMethod = - typeof(DbDataReader).GetRuntimeMethod(nameof(DbDataReader.GetFieldValue), new[] { typeof(int) }); + typeof(DbDataReader).GetRequiredRuntimeMethod(nameof(DbDataReader.GetFieldValue), new[] { typeof(int) }); private static readonly MethodInfo _throwReadValueExceptionMethod = - typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(ThrowReadValueException)); + typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(ThrowReadValueException)); // Coordinating results private static readonly MemberInfo _resultContextValuesMemberInfo @@ -47,43 +48,43 @@ private static readonly MemberInfo _singleQueryResultCoordinatorResultReadyMembe // Performing collection materialization private static readonly MethodInfo _includeReferenceMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(IncludeReference)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(IncludeReference)); private static readonly MethodInfo _initializeIncludeCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(InitializeIncludeCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(InitializeIncludeCollection)); private static readonly MethodInfo _populateIncludeCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(PopulateIncludeCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(PopulateIncludeCollection)); private static readonly MethodInfo _initializeSplitIncludeCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(InitializeSplitIncludeCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(InitializeSplitIncludeCollection)); private static readonly MethodInfo _populateSplitIncludeCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(PopulateSplitIncludeCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(PopulateSplitIncludeCollection)); private static readonly MethodInfo _populateSplitIncludeCollectionAsyncMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(PopulateSplitIncludeCollectionAsync)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(PopulateSplitIncludeCollectionAsync)); private static readonly MethodInfo _initializeCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(InitializeCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(InitializeCollection)); private static readonly MethodInfo _populateCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(PopulateCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(PopulateCollection)); private static readonly MethodInfo _initializeSplitCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(InitializeSplitCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(InitializeSplitCollection)); private static readonly MethodInfo _populateSplitCollectionMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(PopulateSplitCollection)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(PopulateSplitCollection)); private static readonly MethodInfo _populateSplitCollectionAsyncMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(PopulateSplitCollectionAsync)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(PopulateSplitCollectionAsync)); private static readonly MethodInfo _taskAwaiterMethodInfo - = typeof(ShaperProcessingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(TaskAwaiter)); + = typeof(ShaperProcessingExpressionVisitor).GetRequiredDeclaredMethod(nameof(TaskAwaiter)); private static readonly MethodInfo _collectionAccessorAddMethodInfo - = typeof(IClrCollectionAccessor).GetTypeInfo().GetDeclaredMethod(nameof(IClrCollectionAccessor.Add)); + = typeof(IClrCollectionAccessor).GetRequiredDeclaredMethod(nameof(IClrCollectionAccessor.Add)); private readonly RelationalShapedQueryCompilingExpressionVisitor _parentVisitor; private readonly ISet? _tags; @@ -303,7 +304,7 @@ public LambdaExpression ProcessShaper( Expression.Lambda>( Expression.Call(_taskAwaiterMethodInfo, tasks), QueryCompilationContext.QueryContextParameter, - _executionStrategyParameter, + _executionStrategyParameter!, _resultCoordinatorParameter); } else @@ -311,7 +312,7 @@ public LambdaExpression ProcessShaper( relatedDataLoaders = Expression.Lambda>( Expression.Block(_collectionPopulatingExpressions), QueryCompilationContext.QueryContextParameter, - _executionStrategyParameter, + _executionStrategyParameter!, _resultCoordinatorParameter); } } @@ -373,10 +374,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) _materializationContextBindings[parameterExpression] = propertyMap; entityTypeIdentifyingExpressionOffsets[parameterExpression] = propertyMap.Values.Max() + 1; - var updatedExpression = Expression.New( - newExpression.Constructor, - Expression.Constant(ValueBuffer.Empty), - newExpression.Arguments[1]); + var updatedExpression = newExpression.Update( + new[] { Expression.Constant(ValueBuffer.Empty), newExpression.Arguments[1] }); return Expression.Assign(binaryExpression.Left, updatedExpression); } @@ -415,7 +414,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _valuesArrayInitializers!.Add(entityParameter); accessor = Expression.Convert( Expression.ArrayIndex( - _valuesArrayExpression, + _valuesArrayExpression!, Expression.Constant(_valuesArrayInitializers.Count - 1)), entityShaperExpression.Type); } @@ -481,7 +480,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _valuesArrayInitializers!.Add(expressionToAdd); accessor = Expression.Convert( Expression.ArrayIndex( - _valuesArrayExpression, + _valuesArrayExpression!, Expression.Constant(_valuesArrayInitializers.Count - 1)), projectionBindingExpression.Type); } @@ -642,7 +641,7 @@ protected override Expression VisitExtension(Expression extensionExpression) .MakeGenericMethod(includingEntityType, relatedEntityType), collectionIdConstant, Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), - _executionStrategyParameter, + _executionStrategyParameter!, Expression.Constant(_detailedErrorsEnabled), _resultCoordinatorParameter, Expression.Constant(relationalCommandCache), @@ -750,7 +749,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _valuesArrayInitializers!.Add(collectionParameter); accessor = Expression.Convert( Expression.ArrayIndex( - _valuesArrayExpression, + _valuesArrayExpression!, Expression.Constant(_valuesArrayInitializers.Count - 1)), relationalCollectionShaperExpression.Type); @@ -837,7 +836,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _valuesArrayInitializers!.Add(collectionParameter); accessor = Expression.Convert( Expression.ArrayIndex( - _valuesArrayExpression, + _valuesArrayExpression!, Expression.Constant(_valuesArrayInitializers.Count - 1)), relationalSplitCollectionShaperExpression.Type); @@ -847,7 +846,7 @@ protected override Expression VisitExtension(Expression extensionExpression) .MakeGenericMethod(collectionType, elementType, relatedElementType), collectionIdConstant, Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), - _executionStrategyParameter, + _executionStrategyParameter!, Expression.Constant(_detailedErrorsEnabled), _resultCoordinatorParameter, Expression.Constant(relationalCommandCache), @@ -883,11 +882,11 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp && methodCallExpression.Method.GetGenericMethodDefinition() == Infrastructure.ExpressionExtensions.ValueBufferTryReadValueMethod) { - var property = (IProperty)((ConstantExpression)methodCallExpression.Arguments[2]).Value; - var mappingParameter = (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object; + var property = methodCallExpression.Arguments[2].GetConstantValue(); + var mappingParameter = (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object!; var projectionIndex = property == null ? entityTypeIdentifyingExpressionOffsets[mappingParameter] - + (int)((ConstantExpression)methodCallExpression.Arguments[1]).Value + + methodCallExpression.Arguments[1].GetConstantValue() : _materializationContextBindings[mappingParameter][property]; var projection = _selectExpression.Projection[projectionIndex]; @@ -960,7 +959,7 @@ private Expression GenerateKey(Expression expression) private object GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression) => projectionBindingExpression.ProjectionMember != null - ? ((ConstantExpression)_selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value + ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember).GetConstantValue() : (projectionBindingExpression.Index != null ? (object)projectionBindingExpression.Index : projectionBindingExpression.IndexMap)!; @@ -990,7 +989,7 @@ private Expression CreateGetValueExpression( Expression valueExpression = Expression.Call( getMethod.DeclaringType != typeof(DbDataReader) - ? Expression.Convert(dbDataReader, getMethod.DeclaringType) + ? Expression.Convert(dbDataReader, getMethod.DeclaringType!) : (Expression)dbDataReader, getMethod, indexExpression); @@ -1862,7 +1861,8 @@ public bool ContainsCollectionMaterialization(Expression expression) return _containsCollection; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { if (_containsCollection) { diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index fb8584c9f7f..a0f423bc858 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -35,19 +35,19 @@ public class RelationalSqlTranslatingExpressionVisitor : ExpressionVisitor private const string RuntimeParameterPrefix = QueryCompilationContext.QueryParameterPrefix + "entity_equality_"; private static readonly MethodInfo _parameterValueExtractor = - typeof(RelationalSqlTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(ParameterValueExtractor)); + typeof(RelationalSqlTranslatingExpressionVisitor).GetRequiredDeclaredMethod(nameof(ParameterValueExtractor)); private static readonly MethodInfo _parameterListValueExtractor = - typeof(RelationalSqlTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(ParameterListValueExtractor)); + typeof(RelationalSqlTranslatingExpressionVisitor).GetRequiredDeclaredMethod(nameof(ParameterListValueExtractor)); private static readonly MethodInfo _stringEqualsWithStringComparison - = typeof(string).GetRuntimeMethod(nameof(string.Equals), new[] { typeof(string), typeof(StringComparison) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Equals), new[] { typeof(string), typeof(StringComparison) }); private static readonly MethodInfo _stringEqualsWithStringComparisonStatic - = typeof(string).GetRuntimeMethod(nameof(string.Equals), new[] { typeof(string), typeof(string), typeof(StringComparison) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Equals), new[] { typeof(string), typeof(string), typeof(StringComparison) }); private static readonly MethodInfo _objectEqualsMethodInfo - = typeof(object).GetRuntimeMethod(nameof(object.Equals), new[] { typeof(object), typeof(object) }); + = typeof(object).GetRequiredRuntimeMethod(nameof(object.Equals), new[] { typeof(object), typeof(object) }); private readonly QueryCompilationContext _queryCompilationContext; private readonly IModel _model; @@ -296,7 +296,7 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) } /// - protected override Expression? VisitBinary(BinaryExpression binaryExpression) + protected override Expression VisitBinary(BinaryExpression binaryExpression) { Check.NotNull(binaryExpression, nameof(binaryExpression)); @@ -315,16 +315,16 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) var isRightConvertToObject = TryUnwrapConvertToObject(right, out var rightOperand); if (isLeftConvertToObject && isRightConvertToObject) { - left = leftOperand; - right = rightOperand; + left = leftOperand!; + right = rightOperand!; } else if (isLeftConvertToObject && right.IsNullConstantExpression()) { - left = leftOperand; + left = leftOperand!; } else if (isRightConvertToObject && left.IsNullConstantExpression()) { - right = rightOperand; + right = rightOperand!; } var visitedLeft = Visit(left); @@ -334,7 +334,10 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) || 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 == QueryCompilationContext.NotTranslatedExpression ? left : visitedLeft, + visitedRight == QueryCompilationContext.NotTranslatedExpression ? right : visitedRight, + equalsMethod: false, out var result)) { return result; } @@ -349,14 +352,14 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) return TranslationFailed(binaryExpression.Left, visitedLeft, out var sqlLeft) || TranslationFailed(binaryExpression.Right, visitedRight, out var sqlRight) - ? null + ? QueryCompilationContext.NotTranslatedExpression : uncheckedNodeTypeVariant == ExpressionType.Coalesce ? _sqlExpressionFactory.Coalesce(sqlLeft!, sqlRight!) - : (Expression?)_sqlExpressionFactory.MakeBinary( + : _sqlExpressionFactory.MakeBinary( uncheckedNodeTypeVariant, sqlLeft!, sqlRight!, - null); + null) ?? QueryCompilationContext.NotTranslatedExpression; static bool TryUnwrapConvertToObject(Expression expression, out Expression? operand) { @@ -375,7 +378,7 @@ static bool TryUnwrapConvertToObject(Expression expression, out Expression? oper } /// - protected override Expression? VisitConditional(ConditionalExpression conditionalExpression) + protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { Check.NotNull(conditionalExpression, nameof(conditionalExpression)); @@ -386,16 +389,16 @@ static bool TryUnwrapConvertToObject(Expression expression, out Expression? oper return TranslationFailed(conditionalExpression.Test, test, out var sqlTest) || TranslationFailed(conditionalExpression.IfTrue, ifTrue, out var sqlIfTrue) || TranslationFailed(conditionalExpression.IfFalse, ifFalse, out var sqlIfFalse) - ? null + ? QueryCompilationContext.NotTranslatedExpression : _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)); @@ -413,30 +416,30 @@ static bool TryUnwrapConvertToObject(Expression expression, out Expression? oper return projectionBindingExpression.ProjectionMember != null ? ((SelectExpression)projectionBindingExpression.QueryExpression) .GetMappedProjection(projectionBindingExpression.ProjectionMember) - : null; + : QueryCompilationContext.NotTranslatedExpression; case GroupByShaperExpression groupByShaperExpression: return new GroupingElementExpression(groupByShaperExpression.ElementSelector); default: - return null; + return QueryCompilationContext.NotTranslatedExpression; } } /// - protected override Expression? VisitInvocation(InvocationExpression invocationExpression) - => null; + protected override Expression VisitInvocation(InvocationExpression invocationExpression) + => QueryCompilationContext.NotTranslatedExpression; /// - protected override Expression? VisitLambda(Expression lambdaExpression) - => null; + protected override Expression VisitLambda(Expression lambdaExpression) + => QueryCompilationContext.NotTranslatedExpression; /// - protected override Expression? VisitListInit(ListInitExpression listInitExpression) - => null; + protected override Expression VisitListInit(ListInitExpression listInitExpression) + => QueryCompilationContext.NotTranslatedExpression; /// - protected override Expression? VisitMember(MemberExpression memberExpression) + protected override Expression VisitMember(MemberExpression memberExpression) { Check.NotNull(memberExpression, nameof(memberExpression)); @@ -444,17 +447,18 @@ static bool TryUnwrapConvertToObject(Expression expression, out Expression? oper return TryBindMember(innerExpression, MemberIdentity.Create(memberExpression.Member)) ?? (TranslationFailed(memberExpression.Expression, Visit(memberExpression.Expression), out var sqlInnerExpression) - ? null + ? QueryCompilationContext.NotTranslatedExpression : Dependencies.MemberTranslatorProvider.Translate( - sqlInnerExpression, memberExpression.Member, memberExpression.Type, _queryCompilationContext.Logger)); + sqlInnerExpression, memberExpression.Member, memberExpression.Type, _queryCompilationContext.Logger)) + ?? QueryCompilationContext.NotTranslatedExpression; } /// - protected override Expression? VisitMemberInit(MemberInitExpression memberInitExpression) - => GetConstantOrNull(Check.NotNull(memberInitExpression, nameof(memberInitExpression))); + protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) + => GetConstantOrNotTranslated(Check.NotNull(memberInitExpression, nameof(memberInitExpression))); /// - protected override Expression? VisitMethodCall(MethodCallExpression methodCallExpression) + protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); @@ -468,7 +472,8 @@ static bool TryUnwrapConvertToObject(Expression expression, out Expression? oper // EF Indexer property if (methodCallExpression.TryGetIndexerArguments(_model, out source, out propertyName)) { - return TryBindMember(Visit(source), MemberIdentity.Create(propertyName)); + return TryBindMember(Visit(source), MemberIdentity.Create(propertyName)) + ?? QueryCompilationContext.NotTranslatedExpression; } // GroupBy Aggregate case @@ -668,7 +673,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) if (subqueryTranslation.ResultCardinality == ResultCardinality.Enumerable) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var shaperExpression = subqueryTranslation.ShaperExpression; @@ -693,7 +698,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) || convertedType.MakeNullable() == innerExpression.Type)) || IsAggregateResultWithCustomShaper(methodCallExpression.Method))) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var subquery = (SelectExpression)subqueryTranslation.QueryExpression; @@ -738,8 +743,8 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) if (TryRewriteEntityEquality( ExpressionType.Equal, - left ?? methodCallExpression.Object, - right ?? methodCallExpression.Arguments[0], + left == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Object : left, + right == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[0] : right, equalsMethod: true, out var result)) { @@ -754,7 +759,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) } else { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } else if (method.Name == nameof(object.Equals) @@ -774,8 +779,8 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) if (TryRewriteEntityEquality( ExpressionType.Equal, - left ?? methodCallExpression.Arguments[0], - right ?? methodCallExpression.Arguments[1], + left == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[0] : left, + right == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[1] : right, equalsMethod: true, out var result)) { @@ -789,7 +794,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) } else { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } else if (method.IsGenericMethod @@ -798,7 +803,8 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) var enumerable = Visit(methodCallExpression.Arguments[0]); var item = Visit(methodCallExpression.Arguments[1]); - if (TryRewriteContainsEntity(enumerable, item ?? methodCallExpression.Arguments[1], out var result)) + if (TryRewriteContainsEntity(enumerable, + item == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[1] : item, out var result)) { return result; } @@ -810,7 +816,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) } else { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } else if (methodCallExpression.Arguments.Count == 1 @@ -819,7 +825,8 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) var enumerable = Visit(methodCallExpression.Object); var item = Visit(methodCallExpression.Arguments[0]); - if (TryRewriteContainsEntity(enumerable, item ?? methodCallExpression.Arguments[0], out var result)) + if (TryRewriteContainsEntity(enumerable!, + item == QueryCompilationContext.NotTranslatedExpression ? methodCallExpression.Arguments[0] : item, out var result)) { return result; } @@ -832,14 +839,14 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) } else { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } else { if (TranslationFailed(methodCallExpression.Object, Visit(methodCallExpression.Object), out sqlObject)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } arguments = new SqlExpression[methodCallExpression.Arguments.Count]; @@ -848,7 +855,7 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) var argument = methodCallExpression.Arguments[i]; if (TranslationFailed(argument, Visit(argument), out var sqlArgument)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } arguments[i] = sqlArgument!; @@ -874,25 +881,25 @@ static bool IsAggregateResultWithCustomShaper(MethodInfo method) } } - return translation; + return translation ?? QueryCompilationContext.NotTranslatedExpression; } /// - protected override Expression? VisitNew(NewExpression newExpression) - => GetConstantOrNull(Check.NotNull(newExpression, nameof(newExpression))); + protected override Expression VisitNew(NewExpression newExpression) + => GetConstantOrNotTranslated(Check.NotNull(newExpression, nameof(newExpression))); /// - protected override Expression? VisitNewArray(NewArrayExpression newArrayExpression) - => null; + protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) + => QueryCompilationContext.NotTranslatedExpression; /// - 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; + : throw new InvalidOperationException(CoreStrings.TranslationFailed(parameterExpression.Print())); /// - protected override Expression? VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) + protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); @@ -947,7 +954,7 @@ SqlExpression GeneratePredicateTPT(EntityProjectionExpression entityProjectionEx if (entityProjectionExpression.DiscriminatorExpression is CaseExpression caseExpression) { var matchingCaseWhenClauses = caseExpression.WhenClauses - .Where(wc => discriminatorValues.Contains((string)((SqlConstantExpression)wc.Result).Value)) + .Where(wc => discriminatorValues.Contains((string)((SqlConstantExpression)wc.Result).Value!)) .ToList(); return matchingCaseWhenClauses.Count == 1 @@ -995,14 +1002,14 @@ SqlExpression GeneratePredicateTPT(EntityProjectionExpression entityProjectionEx } } - return null; + return QueryCompilationContext.NotTranslatedExpression; static bool HasSiblings(IEntityType entityType) => entityType.BaseType?.GetDirectlyDerivedTypes().Any(i => i != entityType) == true; } /// - protected override Expression? VisitUnary(UnaryExpression unaryExpression) + protected override Expression VisitUnary(UnaryExpression unaryExpression) { Check.NotNull(unaryExpression, nameof(unaryExpression)); @@ -1018,7 +1025,7 @@ static bool HasSiblings(IEntityType entityType) if (TranslationFailed(unaryExpression.Operand, operand, out var sqlOperand)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } switch (unaryExpression.NodeType) @@ -1039,7 +1046,7 @@ static bool HasSiblings(IEntityType entityType) || unaryExpression.Type.UnwrapNullableType() == operand.Type.UnwrapNullableType() || unaryExpression.Type.UnwrapNullableType() == typeof(Enum)) { - return sqlOperand; + return sqlOperand!; } // Introduce explicit cast only if the target type is mapped else we need to client eval @@ -1057,10 +1064,10 @@ static bool HasSiblings(IEntityType entityType) return operand; } - return null; + return QueryCompilationContext.NotTranslatedExpression; } - private Expression? TryBindMember(Expression source, MemberIdentity member) + private Expression? TryBindMember(Expression? source, MemberIdentity member) { if (!(source is EntityReferenceExpression entityReferenceExpression)) { @@ -1089,8 +1096,13 @@ static bool HasSiblings(IEntityType entityType) { if (entityReferenceExpression.ParameterEntity != null) { - return ((EntityProjectionExpression)Visit(entityReferenceExpression.ParameterEntity.ValueBufferExpression)).BindProperty( - property); + var valueBufferExpression = Visit(entityReferenceExpression.ParameterEntity.ValueBufferExpression); + if (valueBufferExpression == QueryCompilationContext.NotTranslatedExpression) + { + return null; + } + + return ((EntityProjectionExpression)valueBufferExpression).BindProperty(property); } if (entityReferenceExpression.SubqueryEntity != null) @@ -1169,14 +1181,14 @@ private static Expression ConvertObjectArrayEqualityComparison(Expression left, .Aggregate((a, b) => Expression.AndAlso(a, b)); } - private static SqlConstantExpression? GetConstantOrNull(Expression expression) + private static Expression GetConstantOrNotTranslated(Expression expression) => CanEvaluate(expression) ? new SqlConstantExpression( Expression.Constant( Expression.Lambda>(Expression.Convert(expression, typeof(object))).Compile().Invoke(), expression.Type), null) - : null; + : QueryCompilationContext.NotTranslatedExpression; private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.NotNullWhen(true)] out Expression? result) { @@ -1206,9 +1218,9 @@ private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.No switch (source) { case SqlConstantExpression sqlConstantExpression: - var values = (IEnumerable)sqlConstantExpression.Value; + var values = (IEnumerable)sqlConstantExpression.Value!; var propertyValueList = - (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(property.ClrType.MakeNullable())); + (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(property.ClrType.MakeNullable()))!; var propertyGetter = property.GetGetter(); foreach (var value in values) { @@ -1222,7 +1234,7 @@ private bool TryRewriteContainsEntity(Expression source, Expression item, [CA.No when sqlParameterExpression.Name.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal): var lambda = Expression.Lambda( Expression.Call( - _parameterListValueExtractor.MakeGenericMethod(entityType.ClrType, property.ClrType.MakeNullable()), + _parameterListValueExtractor.MakeGenericMethod(entityType.ClrType!, property.ClrType.MakeNullable()), QueryCompilationContext.QueryContextParameter, Expression.Constant(sqlParameterExpression.Name, typeof(string)), Expression.Constant(property, typeof(IProperty))), @@ -1522,7 +1534,7 @@ public override Type Type 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 @@ -1532,7 +1544,9 @@ public override ExpressionType NodeType var derivedEntityType = EntityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type); - return derivedEntityType == null ? null : new EntityReferenceExpression(this, derivedEntityType); + return derivedEntityType == null + ? QueryCompilationContext.NotTranslatedExpression + : new EntityReferenceExpression(this, derivedEntityType); } } diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index 0e0440f60b8..ebda99e7b00 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -825,7 +825,7 @@ public virtual SelectExpression Select(IEntityType entityType, string sql, Expre Check.NotNull(sql, nameof(sql)); var tableExpression = new FromSqlExpression( - entityType.GetDefaultMappings().SingleOrDefault().Table.Name.Substring(0, 1).ToLowerInvariant(), sql, sqlArguments); + entityType.GetDefaultMappings().Single().Table.Name.Substring(0, 1).ToLowerInvariant(), sql, sqlArguments); var selectExpression = new SelectExpression(entityType, tableExpression); AddConditions(selectExpression, entityType); diff --git a/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs index 840dbb55467..4e1bf45a712 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/RowNumberExpression.cs @@ -92,7 +92,8 @@ public virtual RowNumberExpression Update( { Check.NotNull(orderings, nameof(orderings)); - return (Partitions == null ? partitions == null : Partitions.SequenceEqual(partitions)) + return ((Partitions == null && partitions == null) + || (Partitions != null && partitions != null && Partitions.SequenceEqual(partitions))) && Orderings.SequenceEqual(orderings) ? this : new RowNumberExpression(partitions, orderings, TypeMapping); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 092d1746d64..6fb8ebb91b7 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -1928,8 +1928,8 @@ private Expression AddJoin( AddJoin(joinType, ref innerSelectExpression, joinPredicate); var transparentIdentifierType = TransparentIdentifierFactory.Create(outerShaper.Type, innerShaper.Type); - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var outerClientEval = Projection.Count > 0; var innerClientEval = innerSelectExpression.Projection.Count > 0; var remapper = new ProjectionBindingExpressionRemappingExpressionVisitor(this); @@ -2231,7 +2231,7 @@ private void AddJoin( limit = offset is SqlConstantExpression offsetConstant && limit is SqlConstantExpression limitConstant ? (SqlExpression)new SqlConstantExpression( - Constant((int)offsetConstant.Value + (int)limitConstant.Value), + Constant((int)offsetConstant.Value! + (int)limitConstant.Value!), limit.TypeMapping) : new SqlBinaryExpression(ExpressionType.Add, offset, limit, limit.Type, limit.TypeMapping); } @@ -2530,14 +2530,14 @@ private void AddJoin( if (transparentIdentifierType != null) { - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); + var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); var projectionMapping = new Dictionary(); foreach (var projection in _projectionMapping) { projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; } - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var innerNullable = joinType == JoinType.LeftJoin || joinType == JoinType.OuterApply; foreach (var projection in innerSelectExpression._projectionMapping) { @@ -2724,9 +2724,10 @@ private sealed class ColumnExpressionFindingExpressionVisitor : ExpressionVisito foreach (var keyValuePair in _columnsUsedInJoinCondition) { var tableAlias = keyValuePair.Key; - if (_columnReferenced[tableAlias] != null) + if (_columnReferenced[tableAlias] != null + && _columnsUsedInJoinCondition[tableAlias] != null) { - _columnReferenced[tableAlias]!.UnionWith(_columnsUsedInJoinCondition[tableAlias]); + _columnReferenced[tableAlias]!.UnionWith(_columnsUsedInJoinCondition[tableAlias]!); } } @@ -2812,7 +2813,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) _tables.Clear(); _tables.AddRange(tables.Select(e => (TableExpressionBase)visitor.Visit(e))); - Predicate = (SqlExpression)visitor.Visit(Predicate); + Predicate = (SqlExpression?)visitor.Visit(Predicate); var groupBy = _groupBy.ToList(); _groupBy.Clear(); @@ -2820,14 +2821,14 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) groupBy.Select(e => (SqlExpression)visitor.Visit(e)) .Where(e => !(e is SqlConstantExpression || e is SqlParameterExpression))); - Having = (SqlExpression)visitor.Visit(Having); + Having = (SqlExpression?)visitor.Visit(Having); var orderings = _orderings.ToList(); _orderings.Clear(); _orderings.AddRange(orderings.Select(e => e.Update((SqlExpression)visitor.Visit(e.Expression)))); - Offset = (SqlExpression)visitor.Visit(Offset); - Limit = (SqlExpression)visitor.Visit(Limit); + Offset = (SqlExpression?)visitor.Visit(Offset); + Limit = (SqlExpression?)visitor.Visit(Limit); return this; } @@ -2902,7 +2903,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } } - var predicate = (SqlExpression)visitor.Visit(Predicate); + var predicate = (SqlExpression?)visitor.Visit(Predicate); changed |= predicate != Predicate; var newGroupBy = _groupBy; @@ -2934,7 +2935,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } } - var havingExpression = (SqlExpression)visitor.Visit(Having); + var havingExpression = (SqlExpression?)visitor.Visit(Having); changed |= havingExpression != Having; var newOrderings = _orderings; @@ -2960,10 +2961,10 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) } } - var offset = (SqlExpression)visitor.Visit(Offset); + var offset = (SqlExpression?)visitor.Visit(Offset); changed |= offset != Offset; - var limit = (SqlExpression)visitor.Visit(Limit); + var limit = (SqlExpression?)visitor.Visit(Limit); changed |= limit != Limit; if (changed) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs index d90353c0c34..fd4a9ba035b 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs @@ -39,7 +39,7 @@ public SqlConstantExpression([NotNull] ConstantExpression constantExpression, [C /// /// The constant value. /// - public virtual object Value + public virtual object? Value => _constantExpression.Value; /// @@ -66,7 +66,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) Print(Value, expressionPrinter); } - private void Print(object value, ExpressionPrinter expressionPrinter) + private void Print(object? value, ExpressionPrinter expressionPrinter) => expressionPrinter.Append(TypeMapping?.GenerateSqlLiteral(value) ?? Value?.ToString() ?? "NULL"); /// @@ -80,7 +80,7 @@ private bool Equals(SqlConstantExpression sqlConstantExpression) => base.Equals(sqlConstantExpression) && ValueEquals(Value, sqlConstantExpression.Value); - private bool ValueEquals(object value1, object value2) + private bool ValueEquals(object? value1, object? value2) { if (value1 == null) { diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs index 71ef190a80b..6f5855a5c4f 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs @@ -328,7 +328,7 @@ public virtual SqlFunctionExpression ApplyTypeMapping([CanBeNull] RelationalType /// This expression if no children changed, or an expression with the updated children. public virtual SqlFunctionExpression Update([CanBeNull] SqlExpression? instance, [CanBeNull] IReadOnlyList? arguments) { - return instance != Instance || !arguments?.SequenceEqual(Arguments) == true + return instance != Instance || (arguments != null && Arguments != null && !arguments.SequenceEqual(Arguments)) ? new SqlFunctionExpression( instance, Schema, @@ -385,7 +385,9 @@ private bool Equals(SqlFunctionExpression sqlFunctionExpression) && Schema == sqlFunctionExpression.Schema && ((Instance == null && sqlFunctionExpression.Instance == null) || (Instance != null && Instance.Equals(sqlFunctionExpression.Instance))) - && Arguments.SequenceEqual(sqlFunctionExpression.Arguments); + && ((Arguments == null && sqlFunctionExpression.Arguments == null) + || (Arguments != null && sqlFunctionExpression.Arguments != null + && Arguments.SequenceEqual(sqlFunctionExpression.Arguments))); /// public override int GetHashCode() diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs index 39afc251c90..e420027b27c 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs @@ -24,11 +24,15 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions public sealed class SqlParameterExpression : SqlExpression { private readonly ParameterExpression _parameterExpression; + private readonly string _name; internal SqlParameterExpression(ParameterExpression parameterExpression, RelationalTypeMapping? typeMapping) : base(parameterExpression.Type.UnwrapNullableType(), typeMapping) { + Check.DebugAssert(parameterExpression.Name != null, "Parameter must have name."); + _parameterExpression = parameterExpression; + _name = parameterExpression.Name; IsNullable = parameterExpression.Type.IsNullableType(); } @@ -36,7 +40,7 @@ internal SqlParameterExpression(ParameterExpression parameterExpression, Relatio /// The name of the parameter. /// public string Name - => _parameterExpression.Name; + => _name; /// /// The bool value indicating if this parameter can have null values. diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index 789312251b7..aca2234f270 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -58,7 +58,7 @@ public SqlNullabilityProcessor( /// /// Dictionary of current parameter values in use. /// - protected virtual IReadOnlyDictionary ParameterValues { get; private set; } + protected virtual IReadOnlyDictionary ParameterValues { get; private set; } /// /// Processes a to apply null semantics and optimize it. @@ -69,7 +69,7 @@ public SqlNullabilityProcessor( /// An optimized select expression. public virtual SelectExpression Process( [NotNull] SelectExpression selectExpression, - [NotNull] IReadOnlyDictionary parameterValues, + [NotNull] IReadOnlyDictionary parameterValues, out bool canCache) { Check.NotNull(selectExpression, nameof(selectExpression)); @@ -681,13 +681,13 @@ protected virtual SqlExpression VisitIn([NotNull] InExpression inExpression, boo if (valuesExpression is SqlConstantExpression sqlConstant) { typeMapping = sqlConstant.TypeMapping; - values = (IEnumerable)sqlConstant.Value; + values = (IEnumerable)sqlConstant.Value!; } else if (valuesExpression is SqlParameterExpression sqlParameter) { DoNotCache(); typeMapping = sqlParameter.TypeMapping; - values = (IEnumerable)ParameterValues[sqlParameter.Name]; + values = (IEnumerable?)ParameterValues[sqlParameter.Name]; if (values == null) { throw new NullReferenceException(); @@ -1397,28 +1397,30 @@ private SqlExpression SimplifyLogicalSqlBinaryExpression(SqlBinaryExpression sql // true || a -> true // false && a -> false // false || a -> a - if (sqlBinaryExpression.Left is SqlConstantExpression newLeftConstant) + if (sqlBinaryExpression.Left is SqlConstantExpression newLeftConstant + && newLeftConstant.Value is bool leftBoolValue) { return sqlBinaryExpression.OperatorType == ExpressionType.AndAlso - ? (bool)newLeftConstant.Value + ? leftBoolValue ? sqlBinaryExpression.Right : newLeftConstant - : (bool)newLeftConstant.Value + : leftBoolValue ? newLeftConstant : sqlBinaryExpression.Right; } - if (sqlBinaryExpression.Right is SqlConstantExpression newRightConstant) + if (sqlBinaryExpression.Right is SqlConstantExpression newRightConstant + && newRightConstant.Value is bool rightBoolValue) { // a && true -> a // a || true -> true // a && false -> false // a || false -> a return sqlBinaryExpression.OperatorType == ExpressionType.AndAlso - ? (bool)newRightConstant.Value + ? rightBoolValue ? sqlBinaryExpression.Left : newRightConstant - : (bool)newRightConstant.Value + : rightBoolValue ? newRightConstant : sqlBinaryExpression.Left; } diff --git a/src/EFCore.SqlServer.NTS/EFCore.SqlServer.NTS.csproj b/src/EFCore.SqlServer.NTS/EFCore.SqlServer.NTS.csproj index 8f97f76f59d..1455844d3ac 100644 --- a/src/EFCore.SqlServer.NTS/EFCore.SqlServer.NTS.csproj +++ b/src/EFCore.SqlServer.NTS/EFCore.SqlServer.NTS.csproj @@ -2,7 +2,7 @@ NetTopologySuite support for the Microsoft SQL Server database provider for Entity Framework Core. - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite Microsoft.EntityFrameworkCore.SqlServer diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs index 6608786f2f7..41a02962e75 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs @@ -22,7 +22,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerGeometryCollectionMemberTranslator : IMemberTranslator { - private static readonly MemberInfo _count = typeof(GeometryCollection).GetRuntimeProperty(nameof(GeometryCollection.Count)); + private static readonly MemberInfo _count = typeof(GeometryCollection).GetRequiredRuntimeProperty(nameof(GeometryCollection.Count)); private readonly ISqlExpressionFactory _sqlExpressionFactory; /// diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs index ccdfee1ace4..98095b46a30 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -23,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerGeometryCollectionMethodTranslator : IMethodCallTranslator { - private static readonly MethodInfo _item = typeof(GeometryCollection).GetRuntimeProperty("Item").GetMethod; + private static readonly MethodInfo _item = typeof(GeometryCollection).GetRequiredRuntimeProperty("Item").GetMethod!; private readonly IRelationalTypeMappingSource _typeMappingSource; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs index b77ab9cdb42..d0c2caeceb3 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs @@ -26,28 +26,28 @@ public class SqlServerGeometryMemberTranslator : IMemberTranslator { private static readonly IDictionary _memberToFunctionName = new Dictionary { - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Area)), "STArea" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Dimension)), "STDimension" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.GeometryType)), "STGeometryType" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.IsEmpty)), "STIsEmpty" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.IsValid)), "STIsValid" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Length)), "STLength" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.NumGeometries)), "STNumGeometries" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.NumPoints)), "STNumPoints" } + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Area)), "STArea" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Dimension)), "STDimension" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.GeometryType)), "STGeometryType" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.IsEmpty)), "STIsEmpty" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.IsValid)), "STIsValid" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Length)), "STLength" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.NumGeometries)), "STNumGeometries" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.NumPoints)), "STNumPoints" } }; private static readonly IDictionary _geometryMemberToFunctionName = new Dictionary { - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Boundary)), "STBoundary" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Centroid)), "STCentroid" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Envelope)), "STEnvelope" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.InteriorPoint)), "STPointOnSurface" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.IsSimple)), "STIsSimple" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.PointOnSurface)), "STPointOnSurface" } + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Boundary)), "STBoundary" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Centroid)), "STCentroid" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Envelope)), "STEnvelope" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.InteriorPoint)), "STPointOnSurface" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.IsSimple)), "STIsSimple" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.PointOnSurface)), "STPointOnSurface" } }; - private static readonly MemberInfo _ogcGeometryType = typeof(Geometry).GetRuntimeProperty(nameof(Geometry.OgcGeometryType)); - private static readonly MemberInfo _srid = typeof(Geometry).GetRuntimeProperty(nameof(Geometry.SRID)); + private static readonly MemberInfo _ogcGeometryType = typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.OgcGeometryType)); + private static readonly MemberInfo _srid = typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.SRID)); private readonly IRelationalTypeMappingSource _typeMappingSource; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs index b9f0b65edd6..cedb9c269b4 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs @@ -27,36 +27,36 @@ public class SqlServerGeometryMethodTranslator : IMethodCallTranslator { private static readonly IDictionary _methodToFunctionName = new Dictionary { - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.AsBinary), Type.EmptyTypes), "STAsBinary" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.AsText), Type.EmptyTypes), "AsTextZM" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Buffer), new[] { typeof(double) }), "STBuffer" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Contains), new[] { typeof(Geometry) }), "STContains" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ConvexHull), Type.EmptyTypes), "STConvexHull" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Difference), new[] { typeof(Geometry) }), "STDifference" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Disjoint), new[] { typeof(Geometry) }), "STDisjoint" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Distance), new[] { typeof(Geometry) }), "STDistance" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.EqualsTopologically), new[] { typeof(Geometry) }), "STEquals" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Intersection), new[] { typeof(Geometry) }), "STIntersection" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Intersects), new[] { typeof(Geometry) }), "STIntersects" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Overlaps), new[] { typeof(Geometry) }), "STOverlaps" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.SymmetricDifference), new[] { typeof(Geometry) }), "STSymDifference" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ToBinary), Type.EmptyTypes), "STAsBinary" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ToText), Type.EmptyTypes), "AsTextZM" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Union), new[] { typeof(Geometry) }), "STUnion" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Within), new[] { typeof(Geometry) }), "STWithin" } + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.AsBinary), Type.EmptyTypes), "STAsBinary" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.AsText), Type.EmptyTypes), "AsTextZM" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Buffer), new[] { typeof(double) }), "STBuffer" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Contains), new[] { typeof(Geometry) }), "STContains" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.ConvexHull), Type.EmptyTypes), "STConvexHull" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Difference), new[] { typeof(Geometry) }), "STDifference" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Disjoint), new[] { typeof(Geometry) }), "STDisjoint" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Distance), new[] { typeof(Geometry) }), "STDistance" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.EqualsTopologically), new[] { typeof(Geometry) }), "STEquals" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Intersection), new[] { typeof(Geometry) }), "STIntersection" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Intersects), new[] { typeof(Geometry) }), "STIntersects" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Overlaps), new[] { typeof(Geometry) }), "STOverlaps" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.SymmetricDifference), new[] { typeof(Geometry) }), "STSymDifference" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.ToBinary), Type.EmptyTypes), "STAsBinary" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.ToText), Type.EmptyTypes), "AsTextZM" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Union), new[] { typeof(Geometry) }), "STUnion" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Within), new[] { typeof(Geometry) }), "STWithin" } }; private static readonly IDictionary _geometryMethodToFunctionName = new Dictionary { - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Crosses), new[] { typeof(Geometry) }), "STCrosses" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Relate), new[] { typeof(Geometry), typeof(string) }), "STRelate" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Touches), new[] { typeof(Geometry) }), "STTouches" } + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Crosses), new[] { typeof(Geometry) }), "STCrosses" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Relate), new[] { typeof(Geometry), typeof(string) }), "STRelate" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Touches), new[] { typeof(Geometry) }), "STTouches" } }; - private static readonly MethodInfo _getGeometryN = typeof(Geometry).GetRuntimeMethod( + private static readonly MethodInfo _getGeometryN = typeof(Geometry).GetRequiredRuntimeMethod( nameof(Geometry.GetGeometryN), new[] { typeof(int) }); - private static readonly MethodInfo _isWithinDistance = typeof(Geometry).GetRuntimeMethod( + private static readonly MethodInfo _isWithinDistance = typeof(Geometry).GetRequiredRuntimeMethod( nameof(Geometry.IsWithinDistance), new[] { typeof(Geometry), typeof(double) }); private readonly IRelationalTypeMappingSource _typeMappingSource; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs index 300ce5e7499..93a6976b845 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs @@ -27,11 +27,11 @@ public class SqlServerLineStringMemberTranslator : IMemberTranslator { private static readonly IDictionary _memberToFunctionName = new Dictionary { - { typeof(LineString).GetRuntimeProperty(nameof(LineString.Count)), "STNumPoints" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.EndPoint)), "STEndPoint" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.IsClosed)), "STIsClosed" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.StartPoint)), "STStartPoint" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.IsRing)), "STIsRing" } + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.Count)), "STNumPoints" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.EndPoint)), "STEndPoint" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.IsClosed)), "STIsClosed" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.StartPoint)), "STStartPoint" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.IsRing)), "STIsRing" } }; private readonly IRelationalTypeMappingSource _typeMappingSource; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs index a71be94de3f..6d8c4d245e7 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -23,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerLineStringMethodTranslator : IMethodCallTranslator { - private static readonly MethodInfo _getPointN = typeof(LineString).GetRuntimeMethod( + private static readonly MethodInfo _getPointN = typeof(LineString).GetRequiredRuntimeMethod( nameof(LineString.GetPointN), new[] { typeof(int) }); private readonly IRelationalTypeMappingSource _typeMappingSource; diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs index 9aa41f3ddea..1ad7efaf352 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs @@ -22,7 +22,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerMultiLineStringMemberTranslator : IMemberTranslator { - private static readonly MemberInfo _isClosed = typeof(MultiLineString).GetRuntimeProperty(nameof(MultiLineString.IsClosed)); + private static readonly MemberInfo _isClosed = typeof(MultiLineString).GetRequiredRuntimeProperty(nameof(MultiLineString.IsClosed)); private readonly ISqlExpressionFactory _sqlExpressionFactory; /// diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs index bbe9df6ef15..ea7574e51db 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs @@ -18,17 +18,17 @@ internal class SqlServerPointMemberTranslator : IMemberTranslator { private static readonly IDictionary _memberToPropertyName = new Dictionary { - { typeof(Point).GetRuntimeProperty(nameof(Point.M)), "M" }, { typeof(Point).GetRuntimeProperty(nameof(Point.Z)), "Z" } + { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.M)), "M" }, { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.Z)), "Z" } }; private static readonly IDictionary _geographyMemberToPropertyName = new Dictionary { - { typeof(Point).GetRuntimeProperty(nameof(Point.X)), "Long" }, { typeof(Point).GetRuntimeProperty(nameof(Point.Y)), "Lat" } + { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.X)), "Long" }, { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.Y)), "Lat" } }; private static readonly IDictionary _geometryMemberToPropertyName = new Dictionary { - { typeof(Point).GetRuntimeProperty(nameof(Point.X)), "STX" }, { typeof(Point).GetRuntimeProperty(nameof(Point.Y)), "STY" } + { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.X)), "STX" }, { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.Y)), "STY" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; @@ -57,7 +57,8 @@ public SqlServerPointMemberTranslator(ISqlExpressionFactory sqlExpressionFactory if (_memberToPropertyName.TryGetValue(member, out var propertyName) || (isGeography ? _geographyMemberToPropertyName.TryGetValue(member, out propertyName) - : _geometryMemberToPropertyName.TryGetValue(member, out propertyName))) + : _geometryMemberToPropertyName.TryGetValue(member, out propertyName)) + && propertyName != null) { return _sqlExpressionFactory.NiladicFunction( instance, diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs index 0bc1bac739b..6f8d6e65397 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs @@ -24,8 +24,8 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerPolygonMemberTranslator : IMemberTranslator { - private static readonly MemberInfo _exteriorRing = typeof(Polygon).GetRuntimeProperty(nameof(Polygon.ExteriorRing)); - private static readonly MemberInfo _numInteriorRings = typeof(Polygon).GetRuntimeProperty(nameof(Polygon.NumInteriorRings)); + private static readonly MemberInfo _exteriorRing = typeof(Polygon).GetRequiredRuntimeProperty(nameof(Polygon.ExteriorRing)); + private static readonly MemberInfo _numInteriorRings = typeof(Polygon).GetRequiredRuntimeProperty(nameof(Polygon.NumInteriorRings)); private static readonly IDictionary _geometryMemberToFunctionName = new Dictionary { diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs index d39aecdf1ae..152fdf35092 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs @@ -24,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerPolygonMethodTranslator : IMethodCallTranslator { - private static readonly MethodInfo _getInteriorRingN = typeof(Polygon).GetRuntimeMethod( + private static readonly MethodInfo _getInteriorRingN = typeof(Polygon).GetRequiredRuntimeMethod( nameof(Polygon.GetInteriorRingN), new[] { typeof(int) }); private readonly IRelationalTypeMappingSource _typeMappingSource; diff --git a/src/EFCore.SqlServer.NTS/build/netstandard2.1/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets b/src/EFCore.SqlServer.NTS/build/net5.0/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets similarity index 100% rename from src/EFCore.SqlServer.NTS/build/netstandard2.1/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets rename to src/EFCore.SqlServer.NTS/build/net5.0/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets diff --git a/src/EFCore.SqlServer/EFCore.SqlServer.csproj b/src/EFCore.SqlServer/EFCore.SqlServer.csproj index 6de9fe6d6cc..ae0477de656 100644 --- a/src/EFCore.SqlServer/EFCore.SqlServer.csproj +++ b/src/EFCore.SqlServer/EFCore.SqlServer.csproj @@ -2,7 +2,7 @@ Microsoft SQL Server database provider for Entity Framework Core. - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.SqlServer diff --git a/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs index 4aa267276a8..a2482a99d7d 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs @@ -146,7 +146,7 @@ public static IndexBuilder IncludeProperties( IncludeProperties( indexBuilder, - includeExpression.GetMemberAccessList().Select(MemberInfoExtensions.GetSimpleMemberName).ToArray()); + includeExpression.GetMemberAccessList().Select(EntityFrameworkMemberInfoExtensions.GetSimpleMemberName).ToArray()); return indexBuilder; } diff --git a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs index d5c51bfae8c..cb64d328a74 100644 --- a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs @@ -105,7 +105,7 @@ protected override Expression VisitCase(CaseExpression caseExpression) var testIsCondition = caseExpression.Operand == null; _isSearchCondition = false; - var operand = (SqlExpression)Visit(caseExpression.Operand); + var operand = (SqlExpression?)Visit(caseExpression.Operand); var whenClauses = new List(); foreach (var whenClause in caseExpression.WhenClauses) { @@ -117,7 +117,7 @@ protected override Expression VisitCase(CaseExpression caseExpression) } _isSearchCondition = false; - var elseResult = (SqlExpression)Visit(caseExpression.ElseResult); + var elseResult = (SqlExpression?)Visit(caseExpression.ElseResult); _isSearchCondition = parentSearchCondition; @@ -218,8 +218,8 @@ protected override Expression VisitIn(InExpression inExpression) _isSearchCondition = false; var item = (SqlExpression)Visit(inExpression.Item); - var subquery = (SelectExpression)Visit(inExpression.Subquery); - var values = (SqlExpression)Visit(inExpression.Values); + var subquery = (SelectExpression?)Visit(inExpression.Subquery); + var values = (SqlExpression?)Visit(inExpression.Values); _isSearchCondition = parentSearchCondition; return ApplyConversion(inExpression.Update(item, values, subquery), condition: true); @@ -239,7 +239,7 @@ protected override Expression VisitLike(LikeExpression likeExpression) _isSearchCondition = false; var match = (SqlExpression)Visit(likeExpression.Match); var pattern = (SqlExpression)Visit(likeExpression.Pattern); - var escapeChar = (SqlExpression)Visit(likeExpression.EscapeChar); + var escapeChar = (SqlExpression?)Visit(likeExpression.EscapeChar); _isSearchCondition = parentSearchCondition; return ApplyConversion(likeExpression.Update(match, pattern, escapeChar), condition: true); @@ -276,7 +276,7 @@ protected override Expression VisitSelect(SelectExpression selectExpression) } _isSearchCondition = true; - var predicate = (SqlExpression)Visit(selectExpression.Predicate); + var predicate = (SqlExpression?)Visit(selectExpression.Predicate); changed |= predicate != selectExpression.Predicate; var groupBy = new List(); @@ -289,7 +289,7 @@ protected override Expression VisitSelect(SelectExpression selectExpression) } _isSearchCondition = true; - var havingExpression = (SqlExpression)Visit(selectExpression.Having); + var havingExpression = (SqlExpression?)Visit(selectExpression.Having); changed |= havingExpression != selectExpression.Having; var orderings = new List(); @@ -301,10 +301,10 @@ protected override Expression VisitSelect(SelectExpression selectExpression) orderings.Add(ordering.Update(orderingExpression)); } - var offset = (SqlExpression)Visit(selectExpression.Offset); + var offset = (SqlExpression?)Visit(selectExpression.Offset); changed |= offset != selectExpression.Offset; - var limit = (SqlExpression)Visit(selectExpression.Limit); + var limit = (SqlExpression?)Visit(selectExpression.Limit); changed |= limit != selectExpression.Limit; _isSearchCondition = parentSearchCondition; @@ -449,7 +449,7 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction var parentSearchCondition = _isSearchCondition; _isSearchCondition = false; - var instance = (SqlExpression)Visit(sqlFunctionExpression.Instance); + var instance = (SqlExpression?)Visit(sqlFunctionExpression.Instance); SqlExpression[]? arguments = default; if (!sqlFunctionExpression.IsNiladic) { diff --git a/src/EFCore.SqlServer/Query/Internal/SkipTakeCollapsingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SkipTakeCollapsingExpressionVisitor.cs index fd1523fffe4..11de36d4ea8 100644 --- a/src/EFCore.SqlServer/Query/Internal/SkipTakeCollapsingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SkipTakeCollapsingExpressionVisitor.cs @@ -22,7 +22,7 @@ public class SkipTakeCollapsingExpressionVisitor : ExpressionVisitor { private readonly ISqlExpressionFactory _sqlExpressionFactory; - private IReadOnlyDictionary _parameterValues; + private IReadOnlyDictionary _parameterValues; private bool _canCache; /// @@ -47,7 +47,7 @@ public SkipTakeCollapsingExpressionVisitor([NotNull] ISqlExpressionFactory sqlEx /// public virtual SelectExpression Process( [NotNull] SelectExpression selectExpression, - [NotNull] IReadOnlyDictionary parametersValues, + [NotNull] IReadOnlyDictionary parametersValues, out bool canCache) { Check.NotNull(selectExpression, nameof(selectExpression)); @@ -91,11 +91,12 @@ bool IsZero(SqlExpression? sqlExpression) { switch (sqlExpression) { - case SqlConstantExpression constant: - return ((int)constant.Value) == 0; + case SqlConstantExpression constant + when constant.Value is int intValue: + return intValue == 0; case SqlParameterExpression parameter: _canCache = false; - return ((int)_parameterValues[parameter.Name]) == 0; + return _parameterValues[parameter.Name] is int value && value == 0; default: return false; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs index 5b65ae9781e..349e245e70c 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerByteArrayMethodTranslator.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -58,7 +59,7 @@ public SqlServerByteArrayMethodTranslator([NotNull] ISqlExpressionFactory sqlExp var sourceTypeMapping = source.TypeMapping; var value = arguments[1] is SqlConstantExpression constantValue - ? (SqlExpression)_sqlExpressionFactory.Constant(new[] { (byte)constantValue.Value }, sourceTypeMapping) + ? (SqlExpression)_sqlExpressionFactory.Constant(new[] { (byte)constantValue.Value! }, sourceTypeMapping) : _sqlExpressionFactory.Convert(arguments[1], typeof(byte[]), sourceTypeMapping); return _sqlExpressionFactory.GreaterThan( diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs index d3e93aaefae..a437b8964d0 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerCompiledQueryCacheKeyGenerator.cs @@ -63,7 +63,7 @@ public SqlServerCompiledQueryCacheKey( _multipleActiveResultSetsEnabled = multipleActiveResultSetsEnabled; } - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is SqlServerCompiledQueryCacheKey sqlServerCompiledQueryCacheKey && Equals(sqlServerCompiledQueryCacheKey); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs index 81e92b4ce33..a533fdeb921 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDataLengthFunctionTranslator.cs @@ -33,31 +33,31 @@ public class SqlServerDataLengthFunctionTranslator : IMethodCallTranslator private static readonly HashSet _methodInfoDataLengthMapping = new HashSet { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(string) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(bool?) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(double?) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(decimal?) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(DateTime?) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(TimeSpan?) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(DateTimeOffset?) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(byte[]) }), - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DataLength), new[] { typeof(DbFunctions), typeof(Guid?) }) }; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs index 33cbfbb8cb5..e5f442c4c57 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs @@ -26,313 +26,313 @@ private readonly Dictionary _methodInfoDateDiffMapping = new Dictionary { { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "year" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "year" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "year" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "year" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "month" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "month" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "month" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "month" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "day" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "day" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "day" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "day" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "hour" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "hour" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "hour" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "hour" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(TimeSpan), typeof(TimeSpan) }), "hour" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(TimeSpan?), typeof(TimeSpan?) }), "hour" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "minute" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "minute" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "minute" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "minute" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(TimeSpan), typeof(TimeSpan) }), "minute" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(TimeSpan?), typeof(TimeSpan?) }), "minute" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "second" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "second" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "second" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "second" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(TimeSpan), typeof(TimeSpan) }), "second" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(TimeSpan?), typeof(TimeSpan?) }), "second" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "millisecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "millisecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "millisecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "millisecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(TimeSpan), typeof(TimeSpan) }), "millisecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(TimeSpan?), typeof(TimeSpan?) }), "millisecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "microsecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "microsecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "microsecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "microsecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(TimeSpan), typeof(TimeSpan) }), "microsecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(TimeSpan?), typeof(TimeSpan?) }), "microsecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "nanosecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "nanosecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "nanosecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "nanosecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(TimeSpan), typeof(TimeSpan) }), "nanosecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(TimeSpan?), typeof(TimeSpan?) }), "nanosecond" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffWeek), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "week" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffWeek), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "week" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffWeek), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "week" }, { - typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateDiffWeek), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "week" diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs index 91f7dd0009f..0f862f5d450 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs @@ -25,20 +25,20 @@ public class SqlServerDateTimeMethodTranslator : IMethodCallTranslator { private readonly Dictionary _methodInfoDatePartMapping = new Dictionary { - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddYears), new[] { typeof(int) }), "year" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMonths), new[] { typeof(int) }), "month" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddDays), new[] { typeof(double) }), "day" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddHours), new[] { typeof(double) }), "hour" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMinutes), new[] { typeof(double) }), "minute" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddSeconds), new[] { typeof(double) }), "second" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }), "millisecond" }, - { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddYears), new[] { typeof(int) }), "year" }, - { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMonths), new[] { typeof(int) }), "month" }, - { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddDays), new[] { typeof(double) }), "day" }, - { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddHours), new[] { typeof(double) }), "hour" }, - { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMinutes), new[] { typeof(double) }), "minute" }, - { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddSeconds), new[] { typeof(double) }), "second" }, - { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMilliseconds), new[] { typeof(double) }), "millisecond" } + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddYears), new[] { typeof(int) }), "year" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddMonths), new[] { typeof(int) }), "month" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddDays), new[] { typeof(double) }), "day" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddHours), new[] { typeof(double) }), "hour" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddMinutes), new[] { typeof(double) }), "minute" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddSeconds), new[] { typeof(double) }), "second" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }), "millisecond" }, + { typeof(DateTimeOffset).GetRequiredRuntimeMethod(nameof(DateTimeOffset.AddYears), new[] { typeof(int) }), "year" }, + { typeof(DateTimeOffset).GetRequiredRuntimeMethod(nameof(DateTimeOffset.AddMonths), new[] { typeof(int) }), "month" }, + { typeof(DateTimeOffset).GetRequiredRuntimeMethod(nameof(DateTimeOffset.AddDays), new[] { typeof(double) }), "day" }, + { typeof(DateTimeOffset).GetRequiredRuntimeMethod(nameof(DateTimeOffset.AddHours), new[] { typeof(double) }), "hour" }, + { typeof(DateTimeOffset).GetRequiredRuntimeMethod(nameof(DateTimeOffset.AddMinutes), new[] { typeof(double) }), "minute" }, + { typeof(DateTimeOffset).GetRequiredRuntimeMethod(nameof(DateTimeOffset.AddSeconds), new[] { typeof(double) }), "second" }, + { typeof(DateTimeOffset).GetRequiredRuntimeMethod(nameof(DateTimeOffset.AddMilliseconds), new[] { typeof(double) }), "millisecond" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; @@ -82,8 +82,9 @@ public SqlServerDateTimeMethodTranslator( if (datePart != "year" && datePart != "month" && arguments[0] is SqlConstantExpression sqlConstant - && ((double)sqlConstant.Value >= int.MaxValue - || (double)sqlConstant.Value <= int.MinValue)) + && sqlConstant.Value is double doubleValue + && (doubleValue >= int.MaxValue + || doubleValue <= int.MinValue)) { return null; } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs index 05481437609..c62e21407d4 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFromPartsFunctionTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -24,17 +25,17 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal public class SqlServerFromPartsFunctionTranslator : IMethodCallTranslator { private static readonly MethodInfo _dateFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod( + .GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int) }); private static readonly MethodInfo _dateTimeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod( + .GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); private static readonly MethodInfo _dateTime2FromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod( + .GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateTime2FromParts), new[] { @@ -50,7 +51,7 @@ public class SqlServerFromPartsFunctionTranslator : IMethodCallTranslator }); private static readonly MethodInfo _dateTimeOffsetFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod( + .GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.DateTimeOffsetFromParts), new[] { @@ -68,12 +69,12 @@ public class SqlServerFromPartsFunctionTranslator : IMethodCallTranslator }); private static readonly MethodInfo _smallDateTimeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod( + .GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.SmallDateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); private static readonly MethodInfo _timeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod( + .GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.TimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) }); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs index fd088d4aa18..08989533f27 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs @@ -28,22 +28,22 @@ public class SqlServerFullTextSearchFunctionsTranslator : IMethodCallTranslator private const string ContainsFunctionName = "CONTAINS"; private static readonly MethodInfo _freeTextMethodInfo - = typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + = typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.FreeText), new[] { typeof(DbFunctions), typeof(string), typeof(string) }); private static readonly MethodInfo _freeTextMethodInfoWithLanguage - = typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + = typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.FreeText), new[] { typeof(DbFunctions), typeof(string), typeof(string), typeof(int) }); private static readonly MethodInfo _containsMethodInfo - = typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + = typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.Contains), new[] { typeof(DbFunctions), typeof(string), typeof(string) }); private static readonly MethodInfo _containsMethodInfoWithLanguage - = typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + = typeof(SqlServerDbFunctionsExtensions).GetRequiredRuntimeMethod( nameof(SqlServerDbFunctionsExtensions.Contains), new[] { typeof(DbFunctions), typeof(string), typeof(string), typeof(int) }); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs index 02cc75770ed..cbf132a660e 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -24,7 +25,7 @@ public class SqlServerIsDateFunctionTranslator : IMethodCallTranslator private readonly ISqlExpressionFactory _sqlExpressionFactory; private static readonly MethodInfo _methodInfo = typeof(SqlServerDbFunctionsExtensions) - .GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.IsDate), new[] { typeof(DbFunctions), typeof(string) }); + .GetRequiredRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.IsDate), new[] { typeof(DbFunctions), typeof(string) }); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs index e0a8d8f123e..a7a9fddec66 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs @@ -25,51 +25,51 @@ public class SqlServerMathTranslator : IMethodCallTranslator { private static readonly Dictionary _supportedMethodTranslations = new Dictionary { - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(decimal) }), "ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(double) }), "ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(float) }), "ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(int) }), "ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(long) }), "ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(sbyte) }), "ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(short) }), "ABS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(decimal) }), "CEILING" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(double) }), "CEILING" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(decimal) }), "FLOOR" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(double) }), "FLOOR" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Pow), new[] { typeof(double), typeof(double) }), "POWER" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Exp), new[] { typeof(double) }), "EXP" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Log10), new[] { typeof(double) }), "LOG10" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Log), new[] { typeof(double) }), "LOG" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Log), new[] { typeof(double), typeof(double) }), "LOG" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sqrt), new[] { typeof(double) }), "SQRT" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Acos), new[] { typeof(double) }), "ACOS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Asin), new[] { typeof(double) }), "ASIN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Atan), new[] { typeof(double) }), "ATAN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Atan2), new[] { typeof(double), typeof(double) }), "ATN2" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Cos), new[] { typeof(double) }), "COS" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sin), new[] { typeof(double) }), "SIN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Tan), new[] { typeof(double) }), "TAN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(decimal) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(double) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(float) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(int) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(long) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(sbyte) }), "SIGN" }, - { typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(short) }), "SIGN" } + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Abs), new[] { typeof(decimal) }), "ABS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Abs), new[] { typeof(double) }), "ABS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Abs), new[] { typeof(float) }), "ABS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Abs), new[] { typeof(int) }), "ABS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Abs), new[] { typeof(long) }), "ABS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Abs), new[] { typeof(sbyte) }), "ABS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Abs), new[] { typeof(short) }), "ABS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(decimal) }), "CEILING" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(double) }), "CEILING" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Floor), new[] { typeof(decimal) }), "FLOOR" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Floor), new[] { typeof(double) }), "FLOOR" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Pow), new[] { typeof(double), typeof(double) }), "POWER" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Exp), new[] { typeof(double) }), "EXP" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Log10), new[] { typeof(double) }), "LOG10" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Log), new[] { typeof(double) }), "LOG" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Log), new[] { typeof(double), typeof(double) }), "LOG" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sqrt), new[] { typeof(double) }), "SQRT" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Acos), new[] { typeof(double) }), "ACOS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Asin), new[] { typeof(double) }), "ASIN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Atan), new[] { typeof(double) }), "ATAN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Atan2), new[] { typeof(double), typeof(double) }), "ATN2" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Cos), new[] { typeof(double) }), "COS" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sin), new[] { typeof(double) }), "SIN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Tan), new[] { typeof(double) }), "TAN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sign), new[] { typeof(decimal) }), "SIGN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sign), new[] { typeof(double) }), "SIGN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sign), new[] { typeof(float) }), "SIGN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sign), new[] { typeof(int) }), "SIGN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sign), new[] { typeof(long) }), "SIGN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sign), new[] { typeof(sbyte) }), "SIGN" }, + { typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Sign), new[] { typeof(short) }), "SIGN" } }; private static readonly IEnumerable _truncateMethodInfos = new[] { - typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(decimal) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(double) }) + typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Truncate), new[] { typeof(decimal) }), + typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Truncate), new[] { typeof(double) }) }; private static readonly IEnumerable _roundMethodInfos = new[] { - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(double) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal), typeof(int) }), - typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(double), typeof(int) }) + typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal) }), + typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Round), new[] { typeof(double) }), + typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal), typeof(int) }), + typeof(Math).GetRequiredRuntimeMethod(nameof(Math.Round), new[] { typeof(double), typeof(int) }) }; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs index 9a0665c91aa..65010fd0463 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs @@ -22,7 +22,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal /// public class SqlServerNewGuidTranslator : IMethodCallTranslator { - private static readonly MethodInfo _methodInfo = typeof(Guid).GetRuntimeMethod(nameof(Guid.NewGuid), Array.Empty()); + private static readonly MethodInfo _methodInfo = typeof(Guid).GetRequiredRuntimeMethod(nameof(Guid.NewGuid), Array.Empty()); private readonly ISqlExpressionFactory _sqlExpressionFactory; /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs index b483bd70968..b19b765b628 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs @@ -40,7 +40,7 @@ public SqlServerParameterBasedSqlProcessor( /// public override SelectExpression Optimize( SelectExpression selectExpression, - IReadOnlyDictionary parametersValues, + IReadOnlyDictionary parametersValues, out bool canCache) { Check.NotNull(selectExpression, nameof(selectExpression)); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs index c551eb6e152..a4338430569 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs @@ -60,18 +60,18 @@ 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 + ? QueryCompilationContext.NotTranslatedExpression + : visitedExpression is SqlBinaryExpression sqlBinary && _arithmeticOperatorTypes.Contains(sqlBinary.OperatorType) && (_dateTimeDataTypes.Contains(GetProviderType(sqlBinary.Left)) || _dateTimeDataTypes.Contains(GetProviderType(sqlBinary.Right))) - ? null - : visitedExpression); + ? QueryCompilationContext.NotTranslatedExpression + : visitedExpression; } /// @@ -80,14 +80,14 @@ 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? VisitUnary(UnaryExpression unaryExpression) + protected override Expression VisitUnary(UnaryExpression unaryExpression) { if (unaryExpression.NodeType == ExpressionType.ArrayLength && unaryExpression.Operand.Type == typeof(byte[])) { if (!(base.Visit(unaryExpression.Operand) is SqlExpression sqlExpression)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } var isBinaryMaxDataType = GetProviderType(sqlExpression) == "varbinary(max)" || sqlExpression is SqlParameterExpression; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index b0173ca83eb..67fde1c7c66 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -25,54 +25,54 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal public class SqlServerStringMethodTranslator : IMethodCallTranslator { private static readonly MethodInfo _indexOfMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string) }); private static readonly MethodInfo _replaceMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); private static readonly MethodInfo _toLowerMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.ToLower), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.ToLower), Array.Empty()); private static readonly MethodInfo _toUpperMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.ToUpper), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.ToUpper), Array.Empty()); private static readonly MethodInfo _substringMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Substring), new[] { typeof(int), typeof(int) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Substring), new[] { typeof(int), typeof(int) }); private static readonly MethodInfo _isNullOrEmptyMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.IsNullOrEmpty), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IsNullOrEmpty), new[] { typeof(string) }); private static readonly MethodInfo _isNullOrWhiteSpaceMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.IsNullOrWhiteSpace), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IsNullOrWhiteSpace), new[] { typeof(string) }); // Method defined in netcoreapp2.0 only private static readonly MethodInfo _trimStartMethodInfoWithoutArgs - = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimStart), Array.Empty()); private static readonly MethodInfo _trimEndMethodInfoWithoutArgs - = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimEnd), Array.Empty()); private static readonly MethodInfo _trimMethodInfoWithoutArgs - = typeof(string).GetRuntimeMethod(nameof(string.Trim), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Trim), Array.Empty()); // Method defined in netstandard2.0 private static readonly MethodInfo _trimStartMethodInfoWithCharArrayArg - = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), new[] { typeof(char[]) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimStart), new[] { typeof(char[]) }); private static readonly MethodInfo _trimEndMethodInfoWithCharArrayArg - = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), new[] { typeof(char[]) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimEnd), new[] { typeof(char[]) }); private static readonly MethodInfo _trimMethodInfoWithCharArrayArg - = typeof(string).GetRuntimeMethod(nameof(string.Trim), new[] { typeof(char[]) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Trim), new[] { typeof(char[]) }); private static readonly MethodInfo _startsWithMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); private static readonly MethodInfo _containsMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); private static readonly MethodInfo _endsWithMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); private static readonly MethodInfo _firstOrDefaultMethodInfoWithoutArgs = typeof(Enumerable).GetRuntimeMethods().Single( diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs index 1a4ca1d1b04..26077a407b6 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerTimeSpanMemberTranslator.cs @@ -59,7 +59,7 @@ public SqlServerTimeSpanMemberTranslator([NotNull] ISqlExpressionFactory sqlExpr Check.NotNull(returnType, nameof(returnType)); Check.NotNull(logger, nameof(logger)); - if (member.DeclaringType == typeof(TimeSpan) && _datePartMappings.TryGetValue(member.Name, out string value)) + if (member.DeclaringType == typeof(TimeSpan) && _datePartMappings.TryGetValue(member.Name, out var value)) { return _sqlExpressionFactory.Function( "DATEPART", new[] { _sqlExpressionFactory.Fragment(value), instance! }, diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs index 4d3893251f6..122f793406a 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs @@ -188,7 +188,7 @@ static int GetEngineEdition(DbConnection connection) using var command = connection.CreateCommand(); command.CommandText = @" SELECT SERVERPROPERTY('EngineEdition');"; - return (int)command.ExecuteScalar(); + return (int)command.ExecuteScalar()!; } static byte GetCompatibilityLevel(DbConnection connection) diff --git a/src/EFCore.Sqlite.Core/EFCore.Sqlite.Core.csproj b/src/EFCore.Sqlite.Core/EFCore.Sqlite.Core.csproj index e2935c83484..47ebd1737c0 100644 --- a/src/EFCore.Sqlite.Core/EFCore.Sqlite.Core.csproj +++ b/src/EFCore.Sqlite.Core/EFCore.Sqlite.Core.csproj @@ -5,7 +5,7 @@ Microsoft.EntityFrameworkCore.Sqlite.Core Microsoft.EntityFrameworkCore.Sqlite SQLite database provider for Entity Framework Core. This package does not include a copy of the native SQLite library. - netstandard2.1 + net5.0 3.6 true $(PackageTags);SQLite @@ -21,10 +21,6 @@ - - - - diff --git a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs index 311d48ed35a..11784612f10 100644 --- a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs +++ b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs @@ -14,7 +14,6 @@ using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyModel; -using RuntimeEnvironment = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment; namespace Microsoft.EntityFrameworkCore.Infrastructure { @@ -127,11 +126,7 @@ private static void FindExtension() if (hasDependencyContext) { var candidateAssets = new Dictionary<(string, string), int>(); -#if NET5_0 -#error Update to use RuntimeEnvironment.RuntimeIdentifier instead -#endif - var rid = AppContext.GetData("RUNTIME_IDENTIFIER") as string - ?? RuntimeEnvironment.GetRuntimeIdentifier(); + var rid = RuntimeInformation.RuntimeIdentifier; var rids = DependencyContext.Default.RuntimeGraph.FirstOrDefault(g => g.Runtime == rid)?.Fallbacks.ToList() ?? new List(); rids.Insert(0, rid); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs index eb42f8cbdb9..bc828f2c319 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteByteArrayMethodTranslator.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -57,7 +58,7 @@ public SqliteByteArrayMethodTranslator([NotNull] ISqlExpressionFactory sqlExpres var source = arguments[0]; var value = arguments[1] is SqlConstantExpression constantValue - ? (SqlExpression)_sqlExpressionFactory.Constant(new[] { (byte)constantValue.Value }, source.TypeMapping) + ? (SqlExpression)_sqlExpressionFactory.Constant(new[] { (byte)constantValue.Value! }, source.TypeMapping) : _sqlExpressionFactory.Function( "char", new[] { arguments[1] }, diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteCharMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteCharMethodTranslator.cs index dc8f9934cf2..8adc6608897 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteCharMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteCharMethodTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -24,8 +25,8 @@ public class SqliteCharMethodTranslator : IMethodCallTranslator { private static readonly Dictionary _supportedMethods = new Dictionary { - { typeof(char).GetRuntimeMethod(nameof(char.ToLower), new[] { typeof(char) }), "lower" }, - { typeof(char).GetRuntimeMethod(nameof(char.ToUpper), new[] { typeof(char) }), "upper" } + { typeof(char).GetRequiredRuntimeMethod(nameof(char.ToLower), new[] { typeof(char) }), "lower" }, + { typeof(char).GetRequiredRuntimeMethod(nameof(char.ToUpper), new[] { typeof(char) }), "upper" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs index f96bee31277..8c473d5c381 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs @@ -23,19 +23,19 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal public class SqliteDateTimeAddTranslator : IMethodCallTranslator { private static readonly MethodInfo _addMilliseconds - = typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }); + = typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }); private static readonly MethodInfo _addTicks - = typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddTicks), new[] { typeof(long) }); + = typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddTicks), new[] { typeof(long) }); private readonly Dictionary _methodInfoToUnitSuffix = new Dictionary { - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddYears), new[] { typeof(int) }), " years" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMonths), new[] { typeof(int) }), " months" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddDays), new[] { typeof(double) }), " days" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddHours), new[] { typeof(double) }), " hours" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMinutes), new[] { typeof(double) }), " minutes" }, - { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddSeconds), new[] { typeof(double) }), " seconds" } + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddYears), new[] { typeof(int) }), " years" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddMonths), new[] { typeof(int) }), " months" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddDays), new[] { typeof(double) }), " days" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddHours), new[] { typeof(double) }), " hours" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddMinutes), new[] { typeof(double) }), " minutes" }, + { typeof(DateTime).GetRequiredRuntimeMethod(nameof(DateTime.AddSeconds), new[] { typeof(double) }), " seconds" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs index b3499545888..93fe90b8efc 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs @@ -26,32 +26,32 @@ public class SqliteMathTranslator : IMethodCallTranslator { private static readonly Dictionary _supportedMethods = new Dictionary { - { typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(double) }), "abs" }, - { typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(float) }), "abs" }, - { typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(int) }), "abs" }, - { typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(long) }), "abs" }, - { typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(sbyte) }), "abs" }, - { typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(short) }), "abs" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(byte), typeof(byte) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(double), typeof(double) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(float), typeof(float) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(int), typeof(int) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(long), typeof(long) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(sbyte), typeof(sbyte) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(short), typeof(short) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(uint), typeof(uint) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Max), new[] { typeof(ushort), typeof(ushort) }), "max" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(byte), typeof(byte) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(double), typeof(double) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(float), typeof(float) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(int), typeof(int) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(long), typeof(long) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(sbyte), typeof(sbyte) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(short), typeof(short) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(uint), typeof(uint) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Min), new[] { typeof(ushort), typeof(ushort) }), "min" }, - { typeof(Math).GetMethod(nameof(Math.Round), new[] { typeof(double) }), "round" }, - { typeof(Math).GetMethod(nameof(Math.Round), new[] { typeof(double), typeof(int) }), "round" } + { typeof(Math).GetRequiredMethod(nameof(Math.Abs), new[] { typeof(double) }), "abs" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Abs), new[] { typeof(float) }), "abs" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Abs), new[] { typeof(int) }), "abs" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Abs), new[] { typeof(long) }), "abs" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Abs), new[] { typeof(sbyte) }), "abs" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Abs), new[] { typeof(short) }), "abs" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(byte), typeof(byte) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(double), typeof(double) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(float), typeof(float) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(int), typeof(int) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(long), typeof(long) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(sbyte), typeof(sbyte) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(short), typeof(short) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(uint), typeof(uint) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Max), new[] { typeof(ushort), typeof(ushort) }), "max" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(byte), typeof(byte) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(double), typeof(double) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(float), typeof(float) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(int), typeof(int) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(long), typeof(long) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(sbyte), typeof(sbyte) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(short), typeof(short) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(uint), typeof(uint) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Min), new[] { typeof(ushort), typeof(ushort) }), "min" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Round), new[] { typeof(double) }), "round" }, + { typeof(Math).GetRequiredMethod(nameof(Math.Round), new[] { typeof(double), typeof(int) }), "round" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs index 70335729590..016529664cf 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs @@ -24,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal public class SqliteRegexMethodTranslator : IMethodCallTranslator { private readonly static MethodInfo _regexIsMatchMethodInfo - = typeof(Regex).GetRuntimeMethod(nameof(Regex.IsMatch), new Type[] { typeof(string), typeof(string) }); + = typeof(Regex).GetRequiredRuntimeMethod(nameof(Regex.IsMatch), new Type[] { typeof(string), typeof(string) }); private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs index b7b48a1b881..eeb239a8bcc 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs @@ -95,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)); @@ -109,13 +109,13 @@ public SqliteSqlTranslatingExpressionVisitor( nullable: true, argumentsPropagateNullability: new[] { true }, typeof(int)) - : null; + : QueryCompilationContext.NotTranslatedExpression; } var visitedExpression = base.VisitUnary(unaryExpression); - if (visitedExpression == null) + if (visitedExpression == QueryCompilationContext.NotTranslatedExpression) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (visitedExpression is SqlUnaryExpression sqlUnary @@ -134,7 +134,7 @@ public SqliteSqlTranslatingExpressionVisitor( if (operandType == typeof(TimeSpan)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } @@ -147,13 +147,13 @@ 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? VisitBinary(BinaryExpression binaryExpression) + protected override Expression VisitBinary(BinaryExpression binaryExpression) { Check.NotNull(binaryExpression, nameof(binaryExpression)); if (!(base.VisitBinary(binaryExpression) is SqlExpression visitedExpression)) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } if (visitedExpression is SqlBinaryExpression sqlBinary) @@ -185,7 +185,7 @@ public SqliteSqlTranslatingExpressionVisitor( && (restrictedTypes.Contains(GetProviderType(sqlBinary.Left)) || restrictedTypes.Contains(GetProviderType(sqlBinary.Right)))) { - return null; + return QueryCompilationContext.NotTranslatedExpression; } } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs index f2008e6f3d6..6ea758b686d 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs @@ -25,60 +25,60 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal public class SqliteStringMethodTranslator : IMethodCallTranslator { private static readonly MethodInfo _indexOfMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string) }); private static readonly MethodInfo _replaceMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); private static readonly MethodInfo _toLowerMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.ToLower), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.ToLower), Array.Empty()); private static readonly MethodInfo _toUpperMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.ToUpper), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.ToUpper), Array.Empty()); private static readonly MethodInfo _substringMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Substring), new[] { typeof(int), typeof(int) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Substring), new[] { typeof(int), typeof(int) }); private static readonly MethodInfo _isNullOrWhiteSpaceMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.IsNullOrWhiteSpace), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IsNullOrWhiteSpace), new[] { typeof(string) }); // Method defined in netcoreapp2.0 only private static readonly MethodInfo _trimStartMethodInfoWithoutArgs - = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimStart), Array.Empty()); private static readonly MethodInfo _trimStartMethodInfoWithCharArg - = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), new[] { typeof(char) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimStart), new[] { typeof(char) }); private static readonly MethodInfo _trimEndMethodInfoWithoutArgs - = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimEnd), Array.Empty()); private static readonly MethodInfo _trimEndMethodInfoWithCharArg - = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), new[] { typeof(char) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimEnd), new[] { typeof(char) }); private static readonly MethodInfo _trimMethodInfoWithoutArgs - = typeof(string).GetRuntimeMethod(nameof(string.Trim), Array.Empty()); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Trim), Array.Empty()); private static readonly MethodInfo _trimMethodInfoWithCharArg - = typeof(string).GetRuntimeMethod(nameof(string.Trim), new[] { typeof(char) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Trim), new[] { typeof(char) }); // Method defined in netstandard2.0 private static readonly MethodInfo _trimStartMethodInfoWithCharArrayArg - = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), new[] { typeof(char[]) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimStart), new[] { typeof(char[]) }); private static readonly MethodInfo _trimEndMethodInfoWithCharArrayArg - = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), new[] { typeof(char[]) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimEnd), new[] { typeof(char[]) }); private static readonly MethodInfo _trimMethodInfoWithCharArrayArg - = typeof(string).GetRuntimeMethod(nameof(string.Trim), new[] { typeof(char[]) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Trim), new[] { typeof(char[]) }); private static readonly MethodInfo _startsWithMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); private static readonly MethodInfo _containsMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Contains), new[] { typeof(string) }); private static readonly MethodInfo _endsWithMethodInfo - = typeof(string).GetRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); + = typeof(string).GetRequiredRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); private static readonly MethodInfo _firstOrDefaultMethodInfoWithoutArgs = typeof(Enumerable).GetRuntimeMethods().Single( diff --git a/src/EFCore.Sqlite.NTS/EFCore.Sqlite.NTS.csproj b/src/EFCore.Sqlite.NTS/EFCore.Sqlite.NTS.csproj index a474ebe2109..e9bd6d09abc 100644 --- a/src/EFCore.Sqlite.NTS/EFCore.Sqlite.NTS.csproj +++ b/src/EFCore.Sqlite.NTS/EFCore.Sqlite.NTS.csproj @@ -5,7 +5,7 @@ Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite Microsoft.EntityFrameworkCore.Sqlite NetTopologySuite support for the SQLite database provider for Entity Framework Core. - netstandard2.1 + net5.0 3.6 true $(PackageTags);SQLite;GIS;NTS;OGC;SpatiaLite diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs index 3e6dbe39fef..8b88f462663 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs @@ -22,7 +22,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal /// public class SqliteGeometryCollectionMemberTranslator : IMemberTranslator { - private static readonly MemberInfo _count = typeof(GeometryCollection).GetRuntimeProperty(nameof(GeometryCollection.Count)); + private static readonly MemberInfo _count = typeof(GeometryCollection).GetRequiredRuntimeProperty(nameof(GeometryCollection.Count)); private readonly ISqlExpressionFactory _sqlExpressionFactory; /// diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs index 0e1e0ae2217..fa5bd14b8e3 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -22,7 +23,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal /// public class SqliteGeometryCollectionMethodTranslator : IMethodCallTranslator { - private static readonly MethodInfo _item = typeof(GeometryCollection).GetRuntimeProperty("Item").GetMethod; + private static readonly MethodInfo _item = typeof(GeometryCollection).GetRequiredRuntimeProperty("Item").GetMethod!; private readonly ISqlExpressionFactory _sqlExpressionFactory; /// diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs index e6c226e7fea..6fbe946a546 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs @@ -25,24 +25,24 @@ public class SqliteGeometryMemberTranslator : IMemberTranslator { private static readonly IDictionary _memberToFunctionName = new Dictionary { - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Area)), "Area" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Boundary)), "Boundary" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Centroid)), "Centroid" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Dimension)), "Dimension" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Envelope)), "Envelope" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.InteriorPoint)), "PointOnSurface" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.IsEmpty)), "IsEmpty" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.IsSimple)), "IsSimple" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.IsValid)), "IsValid" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.Length)), "GLength" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.NumGeometries)), "NumGeometries" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.NumPoints)), "NumPoints" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.PointOnSurface)), "PointOnSurface" }, - { typeof(Geometry).GetRuntimeProperty(nameof(Geometry.SRID)), "SRID" } + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Area)), "Area" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Boundary)), "Boundary" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Centroid)), "Centroid" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Dimension)), "Dimension" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Envelope)), "Envelope" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.InteriorPoint)), "PointOnSurface" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.IsEmpty)), "IsEmpty" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.IsSimple)), "IsSimple" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.IsValid)), "IsValid" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.Length)), "GLength" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.NumGeometries)), "NumGeometries" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.NumPoints)), "NumPoints" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.PointOnSurface)), "PointOnSurface" }, + { typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.SRID)), "SRID" } }; - private static readonly MemberInfo _geometryType = typeof(Geometry).GetRuntimeProperty(nameof(Geometry.GeometryType)); - private static readonly MemberInfo _ogcGeometryType = typeof(Geometry).GetRuntimeProperty(nameof(Geometry.OgcGeometryType)); + private static readonly MemberInfo _geometryType = typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.GeometryType)); + private static readonly MemberInfo _ogcGeometryType = typeof(Geometry).GetRequiredRuntimeProperty(nameof(Geometry.OgcGeometryType)); private readonly ISqlExpressionFactory _sqlExpressionFactory; /// diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs index 85812dc7eb2..ed9e60d971d 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs @@ -26,37 +26,37 @@ public class SqliteGeometryMethodTranslator : IMethodCallTranslator { private static readonly IDictionary _methodToFunctionName = new Dictionary { - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.AsBinary), Type.EmptyTypes), "AsBinary" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.AsText), Type.EmptyTypes), "AsText" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Buffer), new[] { typeof(double) }), "Buffer" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Buffer), new[] { typeof(double), typeof(int) }), "Buffer" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Contains), new[] { typeof(Geometry) }), "Contains" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ConvexHull), Type.EmptyTypes), "ConvexHull" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Crosses), new[] { typeof(Geometry) }), "Crosses" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.CoveredBy), new[] { typeof(Geometry) }), "CoveredBy" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Covers), new[] { typeof(Geometry) }), "Covers" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Difference), new[] { typeof(Geometry) }), "Difference" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Disjoint), new[] { typeof(Geometry) }), "Disjoint" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Distance), new[] { typeof(Geometry) }), "Distance" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.EqualsTopologically), new[] { typeof(Geometry) }), "Equals" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Intersection), new[] { typeof(Geometry) }), "Intersection" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Intersects), new[] { typeof(Geometry) }), "Intersects" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Overlaps), new[] { typeof(Geometry) }), "Overlaps" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Relate), new[] { typeof(Geometry), typeof(string) }), "Relate" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Reverse), Type.EmptyTypes), "ST_Reverse" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.SymmetricDifference), new[] { typeof(Geometry) }), "SymDifference" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ToBinary), Type.EmptyTypes), "AsBinary" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ToText), Type.EmptyTypes), "AsText" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Touches), new[] { typeof(Geometry) }), "Touches" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Union), Type.EmptyTypes), "UnaryUnion" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Union), new[] { typeof(Geometry) }), "GUnion" }, - { typeof(Geometry).GetRuntimeMethod(nameof(Geometry.Within), new[] { typeof(Geometry) }), "Within" } + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.AsBinary), Type.EmptyTypes), "AsBinary" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.AsText), Type.EmptyTypes), "AsText" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Buffer), new[] { typeof(double) }), "Buffer" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Buffer), new[] { typeof(double), typeof(int) }), "Buffer" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Contains), new[] { typeof(Geometry) }), "Contains" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.ConvexHull), Type.EmptyTypes), "ConvexHull" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Crosses), new[] { typeof(Geometry) }), "Crosses" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.CoveredBy), new[] { typeof(Geometry) }), "CoveredBy" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Covers), new[] { typeof(Geometry) }), "Covers" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Difference), new[] { typeof(Geometry) }), "Difference" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Disjoint), new[] { typeof(Geometry) }), "Disjoint" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Distance), new[] { typeof(Geometry) }), "Distance" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.EqualsTopologically), new[] { typeof(Geometry) }), "Equals" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Intersection), new[] { typeof(Geometry) }), "Intersection" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Intersects), new[] { typeof(Geometry) }), "Intersects" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Overlaps), new[] { typeof(Geometry) }), "Overlaps" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Relate), new[] { typeof(Geometry), typeof(string) }), "Relate" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Reverse), Type.EmptyTypes), "ST_Reverse" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.SymmetricDifference), new[] { typeof(Geometry) }), "SymDifference" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.ToBinary), Type.EmptyTypes), "AsBinary" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.ToText), Type.EmptyTypes), "AsText" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Touches), new[] { typeof(Geometry) }), "Touches" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Union), Type.EmptyTypes), "UnaryUnion" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Union), new[] { typeof(Geometry) }), "GUnion" }, + { typeof(Geometry).GetRequiredRuntimeMethod(nameof(Geometry.Within), new[] { typeof(Geometry) }), "Within" } }; - private static readonly MethodInfo _getGeometryN = typeof(Geometry).GetRuntimeMethod( + private static readonly MethodInfo _getGeometryN = typeof(Geometry).GetRequiredRuntimeMethod( nameof(Geometry.GetGeometryN), new[] { typeof(int) }); - private static readonly MethodInfo _isWithinDistance = typeof(Geometry).GetRuntimeMethod( + private static readonly MethodInfo _isWithinDistance = typeof(Geometry).GetRequiredRuntimeMethod( nameof(Geometry.IsWithinDistance), new[] { typeof(Geometry), typeof(double) }); private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs index e7bea4ecdc6..df3ca60fa80 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs @@ -26,11 +26,11 @@ public class SqliteLineStringMemberTranslator : IMemberTranslator private static readonly IDictionary _memberToFunctionName = new Dictionary { - { typeof(LineString).GetRuntimeProperty(nameof(LineString.Count)), "NumPoints" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.EndPoint)), "EndPoint" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.IsClosed)), "IsClosed" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.IsRing)), "IsRing" }, - { typeof(LineString).GetRuntimeProperty(nameof(LineString.StartPoint)), "StartPoint" } + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.Count)), "NumPoints" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.EndPoint)), "EndPoint" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.IsClosed)), "IsClosed" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.IsRing)), "IsRing" }, + { typeof(LineString).GetRequiredRuntimeProperty(nameof(LineString.StartPoint)), "StartPoint" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs index ffbd0c129d7..899db3659ee 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -23,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal public class SqliteLineStringMethodTranslator : IMethodCallTranslator { private static readonly MethodInfo _getPointN - = typeof(LineString).GetRuntimeMethod(nameof(LineString.GetPointN), new[] { typeof(int) }); + = typeof(LineString).GetRequiredRuntimeMethod(nameof(LineString.GetPointN), new[] { typeof(int) }); private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs index 2dbdb9fbc48..5a5918e4504 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs @@ -22,7 +22,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal /// public class SqliteMultiLineStringMemberTranslator : IMemberTranslator { - private static readonly MemberInfo _isClosed = typeof(MultiLineString).GetRuntimeProperty(nameof(MultiLineString.IsClosed)); + private static readonly MemberInfo _isClosed = typeof(MultiLineString).GetRequiredRuntimeProperty(nameof(MultiLineString.IsClosed)); private readonly ISqlExpressionFactory _sqlExpressionFactory; /// diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs index 17738940ebf..e5a88d2908e 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs @@ -25,10 +25,10 @@ public class SqlitePointMemberTranslator : IMemberTranslator { private static readonly IDictionary _memberToFunctionName = new Dictionary { - { typeof(Point).GetRuntimeProperty(nameof(Point.M)), "M" }, - { typeof(Point).GetRuntimeProperty(nameof(Point.X)), "X" }, - { typeof(Point).GetRuntimeProperty(nameof(Point.Y)), "Y" }, - { typeof(Point).GetRuntimeProperty(nameof(Point.Z)), "Z" } + { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.M)), "M" }, + { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.X)), "X" }, + { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.Y)), "Y" }, + { typeof(Point).GetRequiredRuntimeProperty(nameof(Point.Z)), "Z" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs index 9f78b3cd970..318dbddf8bc 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs @@ -26,8 +26,8 @@ public class SqlitePolygonMemberTranslator : IMemberTranslator private static readonly IDictionary _memberToFunctionName = new Dictionary { - { typeof(Polygon).GetRuntimeProperty(nameof(Polygon.ExteriorRing)), "ExteriorRing" }, - { typeof(Polygon).GetRuntimeProperty(nameof(Polygon.NumInteriorRings)), "NumInteriorRing" } + { typeof(Polygon).GetRequiredRuntimeProperty(nameof(Polygon.ExteriorRing)), "ExteriorRing" }, + { typeof(Polygon).GetRequiredRuntimeProperty(nameof(Polygon.NumInteriorRings)), "NumInteriorRing" } }; private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs index ad9ec68a0d9..7df6807abaa 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using JetBrains.Annotations; @@ -23,7 +24,7 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal public class SqlitePolygonMethodTranslator : IMethodCallTranslator { private static readonly MethodInfo _getInteriorRingN - = typeof(Polygon).GetRuntimeMethod(nameof(Polygon.GetInteriorRingN), new[] { typeof(int) }); + = typeof(Polygon).GetRequiredRuntimeMethod(nameof(Polygon.GetInteriorRingN), new[] { typeof(int) }); private readonly ISqlExpressionFactory _sqlExpressionFactory; diff --git a/src/EFCore.Sqlite.NTS/build/netstandard2.1/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets b/src/EFCore.Sqlite.NTS/build/net5.0/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets similarity index 100% rename from src/EFCore.Sqlite.NTS/build/netstandard2.1/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets rename to src/EFCore.Sqlite.NTS/build/net5.0/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets diff --git a/src/EFCore.Sqlite/EFCore.Sqlite.csproj b/src/EFCore.Sqlite/EFCore.Sqlite.csproj index 93b90ef1463..90ae268eab0 100644 --- a/src/EFCore.Sqlite/EFCore.Sqlite.csproj +++ b/src/EFCore.Sqlite/EFCore.Sqlite.csproj @@ -4,7 +4,7 @@ SQLite database provider for Entity Framework Core. - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore.Sqlite $(PackageTags);SQLite diff --git a/src/EFCore.Sqlite/lib/netstandard2.1/_._ b/src/EFCore.Sqlite/lib/net5.0/_._ similarity index 100% rename from src/EFCore.Sqlite/lib/netstandard2.1/_._ rename to src/EFCore.Sqlite/lib/net5.0/_._ diff --git a/src/EFCore.Tools/EFCore.Tools.nuspec b/src/EFCore.Tools/EFCore.Tools.nuspec index f18c10abf7f..aaef2ea2023 100644 --- a/src/EFCore.Tools/EFCore.Tools.nuspec +++ b/src/EFCore.Tools/EFCore.Tools.nuspec @@ -5,7 +5,7 @@ $CommonMetadataElements$ 3.6 - + diff --git a/src/EFCore.Tools/lib/netstandard2.1/_._ b/src/EFCore.Tools/lib/net5.0/_._ similarity index 100% rename from src/EFCore.Tools/lib/netstandard2.1/_._ rename to src/EFCore.Tools/lib/net5.0/_._ diff --git a/src/EFCore/DbFunctions.cs b/src/EFCore/DbFunctions.cs index 23389aa8c7c..7eff596ed09 100644 --- a/src/EFCore/DbFunctions.cs +++ b/src/EFCore/DbFunctions.cs @@ -26,7 +26,7 @@ private DbFunctions() /// /// A string that represents the current object. [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() + public override string? ToString() => base.ToString(); /// @@ -35,7 +35,7 @@ public override string ToString() /// The object to compare with the current object. /// if the specified object is equal to the current object; otherwise, . [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) + public override bool Equals(object? obj) => base.Equals(obj); /// diff --git a/src/EFCore/EF.cs b/src/EFCore/EF.cs index 6193201219f..df2f4ce54d7 100644 --- a/src/EFCore/EF.cs +++ b/src/EFCore/EF.cs @@ -19,7 +19,7 @@ namespace Microsoft.EntityFrameworkCore public static partial class EF { internal static readonly MethodInfo PropertyMethod - = typeof(EF).GetTypeInfo().GetDeclaredMethod(nameof(Property)); + = typeof(EF).GetRequiredDeclaredMethod(nameof(Property)); /// /// diff --git a/src/EFCore/EFCore.csproj b/src/EFCore/EFCore.csproj index 83758dd4145..18b8eb5278f 100644 --- a/src/EFCore/EFCore.csproj +++ b/src/EFCore/EFCore.csproj @@ -7,7 +7,7 @@ Commonly Used Types: Microsoft.EntityFrameworkCore.DbContext Microsoft.EntityFrameworkCore.DbSet - netstandard2.1 + net5.0 3.6 Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore diff --git a/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs b/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs index 1462390ed6e..7d3cfae4928 100644 --- a/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs +++ b/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs @@ -2646,7 +2646,7 @@ internal static readonly MethodInfo StringIncludeMethodInfo /// public static IQueryable Include( [NotNull] this IQueryable source, - [NotNull] [NotParameterized] string navigationPropertyPath) + [NotNull][NotParameterized] string navigationPropertyPath) where TEntity : class { Check.NotNull(source, nameof(source)); @@ -2669,7 +2669,7 @@ source.Provider is EntityQueryProvider internal static readonly MethodInfo IgnoreAutoIncludesMethodInfo = typeof(EntityFrameworkQueryableExtensions) - .GetTypeInfo().GetDeclaredMethod(nameof(IgnoreAutoIncludes)); + .GetRequiredDeclaredMethod(nameof(IgnoreAutoIncludes)); /// /// Specifies that the current Entity Framework LINQ query should not have any @@ -2702,7 +2702,7 @@ source.Provider is EntityQueryProvider internal static readonly MethodInfo IgnoreQueryFiltersMethodInfo = typeof(EntityFrameworkQueryableExtensions) - .GetTypeInfo().GetDeclaredMethod(nameof(IgnoreQueryFilters)); + .GetRequiredDeclaredMethod(nameof(IgnoreQueryFilters)); /// /// Specifies that the current Entity Framework LINQ query should not have any @@ -2738,7 +2738,7 @@ source.Provider is EntityQueryProvider internal static readonly MethodInfo AsNoTrackingMethodInfo = typeof(EntityFrameworkQueryableExtensions) - .GetTypeInfo().GetDeclaredMethod(nameof(AsNoTracking)); + .GetRequiredDeclaredMethod(nameof(AsNoTracking)); /// /// @@ -2786,7 +2786,7 @@ source.Provider is EntityQueryProvider internal static readonly MethodInfo AsNoTrackingWithIdentityResolutionMethodInfo = typeof(EntityFrameworkQueryableExtensions) - .GetTypeInfo().GetDeclaredMethod(nameof(AsNoTrackingWithIdentityResolution)); + .GetRequiredDeclaredMethod(nameof(AsNoTrackingWithIdentityResolution)); /// /// @@ -2914,7 +2914,7 @@ public static IQueryable AsTracking( internal static readonly MethodInfo TagWithMethodInfo = typeof(EntityFrameworkQueryableExtensions) - .GetTypeInfo().GetDeclaredMethod(nameof(TagWith)); + .GetRequiredDeclaredMethod(nameof(TagWith)); /// /// Adds a tag to the collection of tags associated with an EF LINQ query. Tags are query annotations @@ -2934,7 +2934,7 @@ internal static readonly MethodInfo TagWithMethodInfo /// public static IQueryable TagWith( [NotNull] this IQueryable source, - [NotNull] [NotParameterized] string tag) + [NotNull][NotParameterized] string tag) { Check.NotNull(source, nameof(source)); Check.NotEmpty(tag, nameof(tag)); @@ -3037,6 +3037,7 @@ public static Task> ToDictionaryAsync( [NotNull] this IQueryable source, [NotNull] Func keySelector, CancellationToken cancellationToken = default) + where TKey : notnull => ToDictionaryAsync(source, keySelector, e => e, comparer: null, cancellationToken); /// @@ -3076,6 +3077,7 @@ public static Task> ToDictionaryAsync( [NotNull] Func keySelector, [NotNull] IEqualityComparer comparer, CancellationToken cancellationToken = default) + where TKey : notnull => ToDictionaryAsync(source, keySelector, e => e, comparer, cancellationToken); /// @@ -3117,6 +3119,7 @@ public static Task> ToDictionaryAsync keySelector, [NotNull] Func elementSelector, CancellationToken cancellationToken = default) + where TKey : notnull => ToDictionaryAsync(source, keySelector, elementSelector, comparer: null, cancellationToken); /// @@ -3162,6 +3165,7 @@ public static async Task> ToDictionaryAsync elementSelector, [CanBeNull] IEqualityComparer? comparer, CancellationToken cancellationToken = default) + where TKey : notnull { Check.NotNull(source, nameof(source)); Check.NotNull(keySelector, nameof(keySelector)); diff --git a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs index fd2d2efde87..182aa34dc12 100644 --- a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs +++ b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs @@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -48,7 +49,7 @@ public static Expression MakeHasDefaultValue( return Expression.Not( Expression.Call( currentValueExpression, - currentValueExpression.Type.GetMethod("get_HasValue"))); + currentValueExpression.Type.GetRequiredMethod("get_HasValue"))); } var property = propertyBase as IProperty; @@ -122,10 +123,10 @@ var memberInfos var memberInfos = new List(); MemberExpression? memberExpression; - + var unwrappedExpression = RemoveTypeAs(RemoveConvert(memberAccessExpression)); do { - memberExpression = RemoveTypeAs(RemoveConvert(memberAccessExpression)) as MemberExpression; + memberExpression = unwrappedExpression as MemberExpression; if (!(memberExpression?.Member is TMemberInfo memberInfo)) { @@ -134,9 +135,9 @@ var memberInfos memberInfos.Insert(0, memberInfo); - memberAccessExpression = memberExpression.Expression; + unwrappedExpression = RemoveTypeAs(RemoveConvert(memberExpression.Expression)); } - while (RemoveTypeAs(RemoveConvert(memberExpression.Expression)) != parameterExpression); + while (unwrappedExpression != parameterExpression); return memberInfos; } @@ -195,7 +196,8 @@ public static bool IsLogicalNot([NotNull] this UnaryExpression sqlUnaryExpressio && (sqlUnaryExpression.Type == typeof(bool) || sqlUnaryExpression.Type == typeof(bool?)); - private static Expression RemoveConvert(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + private static Expression? RemoveConvert(Expression? expression) { if (expression is UnaryExpression unaryExpression && (expression.NodeType == ExpressionType.Convert @@ -208,7 +210,7 @@ private static Expression RemoveConvert(Expression expression) } private static readonly MethodInfo _objectEqualsMethodInfo - = typeof(object).GetRuntimeMethod(nameof(object.Equals), new[] { typeof(object), typeof(object) }); + = typeof(object).GetRequiredRuntimeMethod(nameof(object.Equals), new[] { typeof(object), typeof(object) }); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Extensions/Internal/TypeExtensions.cs b/src/EFCore/Extensions/Internal/TypeExtensions.cs index f88420267dd..86a25eef257 100644 --- a/src/EFCore/Extensions/Internal/TypeExtensions.cs +++ b/src/EFCore/Extensions/Internal/TypeExtensions.cs @@ -35,7 +35,7 @@ public static bool IsDefaultValue([NotNull] this Type type, [CanBeNull] object v /// 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 static FieldInfo GetFieldInfo([NotNull] this Type type, [NotNull] string fieldName) + public static FieldInfo? GetFieldInfo([NotNull] this Type type, [NotNull] string fieldName) => type.GetRuntimeFields().FirstOrDefault(f => f.Name == fieldName && !f.IsStatic); /// diff --git a/src/EFCore/Extensions/ModelExtensions.cs b/src/EFCore/Extensions/ModelExtensions.cs index 8b98f20c495..ebdf3e752fc 100644 --- a/src/EFCore/Extensions/ModelExtensions.cs +++ b/src/EFCore/Extensions/ModelExtensions.cs @@ -175,6 +175,7 @@ public static PropertyAccessMode GetPropertyAccessMode([NotNull] this IModel mod public static bool IsIndexerMethod([NotNull] this IModel model, [NotNull] MethodInfo methodInfo) => !methodInfo.IsStatic && methodInfo.IsSpecialName + && methodInfo.DeclaringType != null && model.AsModel().FindIndexerPropertyInfo(methodInfo.DeclaringType) is PropertyInfo indexerProperty && (methodInfo == indexerProperty.GetMethod || methodInfo == indexerProperty.SetMethod); diff --git a/src/EFCore/Extensions/PropertyExtensions.cs b/src/EFCore/Extensions/PropertyExtensions.cs index a497f85e751..3931a0f811f 100644 --- a/src/EFCore/Extensions/PropertyExtensions.cs +++ b/src/EFCore/Extensions/PropertyExtensions.cs @@ -376,12 +376,12 @@ public NullableComparer(IEqualityComparer comparer) _comparer = comparer; } - public bool Equals(TNullableKey x, TNullableKey y) + public bool Equals(TNullableKey? x, TNullableKey? y) => (x == null && y == null) || (x != null && y != null && _comparer.Equals(x, y)); public int GetHashCode(TNullableKey obj) - => _comparer.GetHashCode(obj); + => obj is null ? 0 : _comparer.GetHashCode(obj); } /// diff --git a/src/EFCore/Infrastructure/Annotatable.cs b/src/EFCore/Infrastructure/Annotatable.cs index ecfad36c733..8676405f79e 100644 --- a/src/EFCore/Infrastructure/Annotatable.cs +++ b/src/EFCore/Infrastructure/Annotatable.cs @@ -153,7 +153,6 @@ public virtual void SetAnnotation(string name, object? value) return null; } - // TODO-NULLABLE: Put MemberNotNull on FindAnnotation when we target net5.0 _annotations!.Remove(name); if (_annotations.Count == 0) diff --git a/src/EFCore/Infrastructure/ExpressionExtensions.cs b/src/EFCore/Infrastructure/ExpressionExtensions.cs index d5d9a9997e0..af70a95eb51 100644 --- a/src/EFCore/Infrastructure/ExpressionExtensions.cs +++ b/src/EFCore/Infrastructure/ExpressionExtensions.cs @@ -79,14 +79,15 @@ public static Expression Assign( BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { memberExpression, valueExpression }, - null); + null)!; } return Expression.Assign(memberExpression, valueExpression); } private static readonly Type _assignBinaryExpressionType - = typeof(Expression).Assembly.GetType("System.Linq.Expressions.AssignBinaryExpression"); + // TODO-Nullable: Somethings are unexplainable + = typeof(Expression).Assembly.GetType("System.Linq.Expressions.AssignBinaryExpression", throwOnError: true)!; /// /// If the given a method-call expression represents a call to , then this @@ -105,7 +106,7 @@ public static bool TryGetEFPropertyArguments( && methodCallExpression.Arguments[1] is ConstantExpression propertyNameExpression) { entityExpression = methodCallExpression.Arguments[0]; - propertyName = (string)propertyNameExpression.Value; + propertyName = (string)propertyNameExpression.Value!; return true; } @@ -131,8 +132,9 @@ public static bool TryGetIndexerArguments( if (model.IsIndexerMethod(methodCallExpression.Method) && methodCallExpression.Arguments[0] is ConstantExpression propertyNameExpression) { - entityExpression = methodCallExpression.Object; - propertyName = (string)propertyNameExpression.Value; + entityExpression = methodCallExpression.Object!; + propertyName = (string)propertyNameExpression.Value!; + return true; } @@ -194,7 +196,7 @@ public static bool TryGetIndexerArguments( { var propertyGetter = propertyInfo.GetMethod; var interfaceMapping = parameterType.GetTypeInfo().GetRuntimeInterfaceMap(declaringType); - var index = Array.FindIndex(interfaceMapping.InterfaceMethods, p => propertyGetter.Equals(p)); + var index = Array.FindIndex(interfaceMapping.InterfaceMethods, p => p.Equals(propertyGetter)); var targetMethod = interfaceMapping.TargetMethods[index]; foreach (var runtimeProperty in parameterType.GetRuntimeProperties()) { @@ -315,8 +317,7 @@ public static Expression CreateValueBufferReadValueExpression( /// /// public static readonly MethodInfo ValueBufferTryReadValueMethod - = typeof(ExpressionExtensions).GetTypeInfo() - .GetDeclaredMethod(nameof(ValueBufferTryReadValue)); + = typeof(ExpressionExtensions).GetRequiredDeclaredMethod(nameof(ValueBufferTryReadValue)); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static TValue ValueBufferTryReadValue( diff --git a/src/EFCore/Infrastructure/IndentedStringBuilder.cs b/src/EFCore/Infrastructure/IndentedStringBuilder.cs index 708e994bdc9..133793a0718 100644 --- a/src/EFCore/Infrastructure/IndentedStringBuilder.cs +++ b/src/EFCore/Infrastructure/IndentedStringBuilder.cs @@ -94,7 +94,7 @@ public virtual IndentedStringBuilder AppendLines([NotNull] string value, bool sk using (var reader = new StringReader(value)) { var first = true; - string line; + string? line; while ((line = reader.ReadLine()) != null) { if (first) diff --git a/src/EFCore/Infrastructure/MethodInfoExtensions.cs b/src/EFCore/Infrastructure/MethodInfoExtensions.cs index e40e5fcbff8..8a77d38ff9c 100644 --- a/src/EFCore/Infrastructure/MethodInfoExtensions.cs +++ b/src/EFCore/Infrastructure/MethodInfoExtensions.cs @@ -19,7 +19,7 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// public static class MethodInfoExtensions { - private static readonly string _efTypeName = typeof(EF).FullName; + private static readonly string _efTypeName = typeof(EF).FullName!; /// /// Returns if the given method is . diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index 9e7d4856c2f..590adbc3e98 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -2953,7 +2953,7 @@ public override string OnTypeMemberIgnored(string name) } var data = new List>(); - var valueConverters = new Dictionary(StringComparer.Ordinal); + var valueConverters = new Dictionary(StringComparer.Ordinal); var properties = GetProperties() .Concat(GetNavigations()) .Concat(GetSkipNavigations()) diff --git a/src/EFCore/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs index 461e029e780..b2717b0f31f 100644 --- a/src/EFCore/Metadata/Internal/Model.cs +++ b/src/EFCore/Metadata/Internal/Model.cs @@ -850,14 +850,16 @@ public virtual bool IsOwned([NotNull] Type type) return null; } - while (type != null) + var currentType = type; + + while (currentType != null) { - if (ownedTypes.TryGetValue(GetDisplayName(type), out var configurationSource)) + if (ownedTypes.TryGetValue(GetDisplayName(currentType), out var configurationSource)) { return configurationSource; } - type = type.BaseType; + currentType = currentType.BaseType; } return null; diff --git a/src/EFCore/Metadata/Internal/Navigation.cs b/src/EFCore/Metadata/Internal/Navigation.cs index 5fad9adfc7f..157def6b4e8 100644 --- a/src/EFCore/Metadata/Internal/Navigation.cs +++ b/src/EFCore/Metadata/Internal/Navigation.cs @@ -211,7 +211,7 @@ public static bool IsCompatible( bool? shouldBeCollection, bool shouldThrow) { - if (!navigationProperty.DeclaringType.IsAssignableFrom(sourceClrType)) + if (!navigationProperty.DeclaringType!.IsAssignableFrom(sourceClrType)) { if (shouldThrow) { diff --git a/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs b/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs index 5d9294020aa..bdb62973869 100644 --- a/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs +++ b/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; @@ -40,6 +41,7 @@ private static readonly MethodInfo _genericCreate private static PropertyAccessors CreateGeneric(IPropertyBase propertyBase) { var property = propertyBase as IProperty; + return new PropertyAccessors( CreateCurrentValueGetter(propertyBase, useStoreGeneratedValues: true), CreateCurrentValueGetter(propertyBase, useStoreGeneratedValues: false), diff --git a/src/EFCore/Metadata/Internal/PropertyBase.cs b/src/EFCore/Metadata/Internal/PropertyBase.cs index 7ed4b1e0842..52172bec9a3 100644 --- a/src/EFCore/Metadata/Internal/PropertyBase.cs +++ b/src/EFCore/Metadata/Internal/PropertyBase.cs @@ -154,14 +154,12 @@ public virtual void SetConfigurationSource(ConfigurationSource configurationSour /// 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 static FieldInfo GetFieldInfo( + public static FieldInfo? GetFieldInfo( [NotNull] string fieldName, [NotNull] TypeBase type, - [CanBeNull] string propertyName, + [NotNull] string propertyName, bool shouldThrow) { - Check.DebugAssert(propertyName != null || !shouldThrow, "propertyName is null"); - if (!type.GetRuntimeFields()!.TryGetValue(fieldName, out var fieldInfo) && shouldThrow) { @@ -252,7 +250,7 @@ public static bool IsCompatible( Check.DebugAssert(propertyName != null || !shouldThrow, "propertyName is null"); if (entityType == null - || !fieldInfo.DeclaringType.IsAssignableFrom(entityType)) + || !fieldInfo.DeclaringType!.IsAssignableFrom(entityType)) { if (shouldThrow) { @@ -396,7 +394,7 @@ public virtual IComparer CurrentValueComparer ref _currentValueComparer, this, p => new CurrentValueComparerFactory().Create(p)); private static readonly MethodInfo _containsKeyMethod = - typeof(IDictionary).GetMethod(nameof(IDictionary.ContainsKey)); + typeof(IDictionary).GetRequiredMethod(nameof(IDictionary.ContainsKey), new[] { typeof(string) }); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/Internal/SkipNavigationComparer.cs b/src/EFCore/Metadata/Internal/SkipNavigationComparer.cs index e822e23a782..61f5d21eb39 100644 --- a/src/EFCore/Metadata/Internal/SkipNavigationComparer.cs +++ b/src/EFCore/Metadata/Internal/SkipNavigationComparer.cs @@ -34,11 +34,15 @@ private SkipNavigationComparer() /// 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 int Compare(SkipNavigation x, SkipNavigation y) - { - var result = StringComparer.Ordinal.Compare(x.Name, y.Name); - - return result != 0 ? result : EntityTypeFullNameComparer.Instance.Compare(x.DeclaringEntityType, y.DeclaringEntityType); - } + public int Compare(SkipNavigation? x, SkipNavigation? y) + => (x, y) switch + { + (not null, null) => 1, + (null, not null) => -1, + (null, null) => 0, + (not null, not null) => StringComparer.Ordinal.Compare(x!.Name, y!.Name) is var compare && compare != 0 + ? compare + : EntityTypeFullNameComparer.Instance.Compare(x.DeclaringEntityType, y.DeclaringEntityType) + }; } } diff --git a/src/EFCore/Query/EntityShaperExpression.cs b/src/EFCore/Query/EntityShaperExpression.cs index 09ac90e8c40..8bca1cc2074 100644 --- a/src/EFCore/Query/EntityShaperExpression.cs +++ b/src/EFCore/Query/EntityShaperExpression.cs @@ -31,8 +31,7 @@ namespace Microsoft.EntityFrameworkCore.Query public class EntityShaperExpression : Expression, IPrintableExpression { private static readonly MethodInfo _createUnableToDiscriminateException - = typeof(EntityShaperExpression).GetTypeInfo() - .GetDeclaredMethod(nameof(CreateUnableToDiscriminateException)); + = typeof(EntityShaperExpression).GetRequiredDeclaredMethod(nameof(CreateUnableToDiscriminateException)); [UsedImplicitly] private static Exception CreateUnableToDiscriminateException(IEntityType entityType, object discriminator) @@ -268,7 +267,7 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) expressionPrinter.AppendLine(nameof(EntityShaperExpression) + ": "); using (expressionPrinter.Indent()) { - expressionPrinter.AppendLine(EntityType.ToString()); + expressionPrinter.AppendLine(EntityType.Name); expressionPrinter.AppendLine(nameof(ValueBufferExpression) + ": "); using (expressionPrinter.Indent()) { diff --git a/src/EFCore/Query/EvaluatableExpressionFilter.cs b/src/EFCore/Query/EvaluatableExpressionFilter.cs index 29e1ca767d9..bffec2e8662 100644 --- a/src/EFCore/Query/EvaluatableExpressionFilter.cs +++ b/src/EFCore/Query/EvaluatableExpressionFilter.cs @@ -30,31 +30,31 @@ public class EvaluatableExpressionFilter : IEvaluatableExpressionFilter // Hence we don't evaluate them. See issue#2069 private static readonly PropertyInfo _dateTimeNow - = typeof(DateTime).GetTypeInfo().GetDeclaredProperty(nameof(DateTime.Now)); + = typeof(DateTime).GetRequiredDeclaredProperty(nameof(DateTime.Now)); private static readonly PropertyInfo _dateTimeUtcNow - = typeof(DateTime).GetTypeInfo().GetDeclaredProperty(nameof(DateTime.UtcNow)); + = typeof(DateTime).GetRequiredDeclaredProperty(nameof(DateTime.UtcNow)); private static readonly PropertyInfo _dateTimeToday - = typeof(DateTime).GetTypeInfo().GetDeclaredProperty(nameof(DateTime.Today)); + = typeof(DateTime).GetRequiredDeclaredProperty(nameof(DateTime.Today)); private static readonly PropertyInfo _dateTimeOffsetNow - = typeof(DateTimeOffset).GetTypeInfo().GetDeclaredProperty(nameof(DateTimeOffset.Now)); + = typeof(DateTimeOffset).GetRequiredDeclaredProperty(nameof(DateTimeOffset.Now)); private static readonly PropertyInfo _dateTimeOffsetUtcNow - = typeof(DateTimeOffset).GetTypeInfo().GetDeclaredProperty(nameof(DateTimeOffset.UtcNow)); + = typeof(DateTimeOffset).GetRequiredDeclaredProperty(nameof(DateTimeOffset.UtcNow)); private static readonly MethodInfo _guidNewGuid - = typeof(Guid).GetTypeInfo().GetDeclaredMethod(nameof(Guid.NewGuid)); + = typeof(Guid).GetRequiredDeclaredMethod(nameof(Guid.NewGuid)); private static readonly MethodInfo _randomNextNoArgs - = typeof(Random).GetRuntimeMethod(nameof(Random.Next), Array.Empty()); + = typeof(Random).GetRequiredRuntimeMethod(nameof(Random.Next), Array.Empty()); private static readonly MethodInfo _randomNextOneArg - = typeof(Random).GetRuntimeMethod(nameof(Random.Next), new[] { typeof(int) }); + = typeof(Random).GetRequiredRuntimeMethod(nameof(Random.Next), new[] { typeof(int) }); private static readonly MethodInfo _randomNextTwoArgs - = typeof(Random).GetRuntimeMethod(nameof(Random.Next), new[] { typeof(int), typeof(int) }); + = typeof(Random).GetRequiredRuntimeMethod(nameof(Random.Next), new[] { typeof(int), typeof(int) }); /// /// diff --git a/src/EFCore/Query/ExpressionEqualityComparer.cs b/src/EFCore/Query/ExpressionEqualityComparer.cs index f964780639c..2f6b34d1598 100644 --- a/src/EFCore/Query/ExpressionEqualityComparer.cs +++ b/src/EFCore/Query/ExpressionEqualityComparer.cs @@ -18,7 +18,7 @@ namespace Microsoft.EntityFrameworkCore.Query /// /// A comparer which implements for . /// - public sealed class ExpressionEqualityComparer : IEqualityComparer + public sealed class ExpressionEqualityComparer : IEqualityComparer { /// /// Creates a new . @@ -218,7 +218,7 @@ public int GetHashCode(Expression obj) return hash.ToHashCode(); - void AddToHashIfNotNull(object t) + void AddToHashIfNotNull(object? t) { if (t != null) { @@ -226,7 +226,7 @@ void AddToHashIfNotNull(object t) } } - void AddExpressionToHashIfNotNull(Expression t) + void AddExpressionToHashIfNotNull(Expression? t) { if (t != null) { @@ -286,14 +286,14 @@ void AddMemberBindingsToHash(IReadOnlyList memberBindings) /// The left expression. /// The right expression. /// if the expressions are equal, otherwise. - public bool Equals(Expression x, Expression y) + public bool Equals(Expression? x, Expression? y) => new ExpressionComparer().Compare(x, y); private struct ExpressionComparer { private Dictionary _parameterScope; - public bool Compare(Expression left, Expression right) + public bool Compare(Expression? left, Expression? right) { if (left == right) { @@ -512,7 +512,7 @@ private bool CompareExpressionList(IReadOnlyList a, IReadOnlyList a, IReadOnlyList b) + private bool CompareMemberList(IReadOnlyList? a, IReadOnlyList? b) { if (ReferenceEquals(a, b)) { diff --git a/src/EFCore/Query/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs index 38f8cdfe66a..1d63c1d5482 100644 --- a/src/EFCore/Query/ExpressionPrinter.cs +++ b/src/EFCore/Query/ExpressionPrinter.cs @@ -37,7 +37,7 @@ public class ExpressionPrinter : ExpressionVisitor }; private readonly IndentedStringBuilder _stringBuilder; - private readonly Dictionary _parametersInScope; + private readonly Dictionary _parametersInScope; private readonly List _namelessParameters; private readonly List _encounteredParameters; @@ -69,7 +69,7 @@ public class ExpressionPrinter : ExpressionVisitor public ExpressionPrinter() { _stringBuilder = new IndentedStringBuilder(); - _parametersInScope = new Dictionary(); + _parametersInScope = new Dictionary(); _namelessParameters = new List(); _encounteredParameters = new List(); } @@ -457,7 +457,7 @@ protected override Expression VisitConstant(ConstantExpression constantExpressio return constantExpression; } - private void Print(object value) + private void Print(object? value) { if (value is IEnumerable enumerable && !(value is string)) @@ -494,7 +494,7 @@ private void Print(object value) stringValue = $@"""{stringValue}"""; } - _stringBuilder.Append(stringValue); + _stringBuilder.Append(stringValue ?? "Unknown"); } /// @@ -590,7 +590,7 @@ protected override Expression VisitMember(MemberExpression memberExpression) else { // ReSharper disable once PossibleNullReferenceException - _stringBuilder.Append(memberExpression.Member.DeclaringType.Name); + _stringBuilder.Append(memberExpression.Member.DeclaringType?.Name ?? "MethodWithoutDeclaringType"); } _stringBuilder.Append("." + memberExpression.Member.Name); @@ -699,7 +699,7 @@ var argumentNames ? extensionMethod ? method.GetParameters().Skip(1).Select(p => p.Name).ToList() : method.GetParameters().Select(p => p.Name).ToList() - : new List(); + : new List(); IDisposable? indent = null; @@ -880,12 +880,12 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres if (Verbose) { Append("(Unhandled parameter: "); - Append(parameterExpression.Name); + Append(parameterExpression.Name ?? "NoNameParameter"); Append(")"); } else { - Append(parameterExpression.Name); + Append(parameterExpression.Name ?? "NoNameParameter"); } } diff --git a/src/EFCore/Query/Internal/EntityMaterializerSource.cs b/src/EFCore/Query/Internal/EntityMaterializerSource.cs index 872a61e1e47..99f35addede 100644 --- a/src/EFCore/Query/Internal/EntityMaterializerSource.cs +++ b/src/EFCore/Query/Internal/EntityMaterializerSource.cs @@ -151,9 +151,8 @@ static Expression CreateMemberAssignment(Expression parameter, MemberInfo member private ConcurrentDictionary> Materializers => LazyInitializer.EnsureInitialized( - // TODO-NULLABLE: LazyInitializer not yet null-annotated in netstandard2.1, can remove bang after targeting net5.0 ref _materializers, - () => new ConcurrentDictionary>())!; + () => new ConcurrentDictionary>()); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Query/Internal/EntityQueryProvider.cs b/src/EFCore/Query/Internal/EntityQueryProvider.cs index d7f0607ec25..75d68027aa6 100644 --- a/src/EFCore/Query/Internal/EntityQueryProvider.cs +++ b/src/EFCore/Query/Internal/EntityQueryProvider.cs @@ -69,7 +69,7 @@ public virtual IQueryable CreateQuery(Expression expression) public virtual IQueryable CreateQuery(Expression expression) => (IQueryable)_genericCreateQueryMethod .MakeGenericMethod(expression.Type.GetSequenceType()) - .Invoke(this, new object[] { expression }); + .Invoke(this, new object[] { expression })!; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -88,7 +88,7 @@ public virtual TResult Execute(Expression expression) /// public virtual object Execute(Expression expression) => _genericExecuteMethod.MakeGenericMethod(expression.Type) - .Invoke(_queryCompiler, new object[] { expression }); + .Invoke(_queryCompiler, new object[] { expression })!; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Query/Internal/IParameterValues.cs b/src/EFCore/Query/Internal/IParameterValues.cs index 25ff48999f3..2ea64ac4388 100644 --- a/src/EFCore/Query/Internal/IParameterValues.cs +++ b/src/EFCore/Query/Internal/IParameterValues.cs @@ -22,7 +22,7 @@ public interface IParameterValues /// 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. /// - IReadOnlyDictionary ParameterValues { get; } + IReadOnlyDictionary ParameterValues { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -30,6 +30,6 @@ public interface IParameterValues /// 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. /// - void AddParameter([NotNull] string name, [CanBeNull] object value); + void AddParameter([NotNull] string name, [CanBeNull] object? value); } } diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs index 083b991507d..ea94b338492 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs @@ -27,7 +27,7 @@ public partial class NavigationExpandingExpressionVisitor private class ExpandingExpressionVisitor : ExpressionVisitor { private static readonly MethodInfo _objectEqualsMethodInfo - = typeof(object).GetRuntimeMethod(nameof(object.Equals), new[] { typeof(object), typeof(object) }); + = typeof(object).GetRequiredRuntimeMethod(nameof(object.Equals), new[] { typeof(object), typeof(object) }); private readonly NavigationExpandingExpressionVisitor _navigationExpandingExpressionVisitor; private readonly NavigationExpansionExpression _source; @@ -87,7 +87,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp { source = Visit(source); return TryExpandNavigation(source, MemberIdentity.Create(navigationName)) - ?? methodCallExpression.Update(null, new[] { source, methodCallExpression.Arguments[1] }); + // TODO-Nullable bug + ?? methodCallExpression.Update(null!, new[] { source, methodCallExpression.Arguments[1] }); } if (methodCallExpression.TryGetIndexerArguments(Model, out source, out navigationName)) @@ -100,8 +101,13 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return base.VisitMethodCall(methodCallExpression); } - private Expression? TryExpandNavigation(Expression root, MemberIdentity memberIdentity) + private Expression? TryExpandNavigation(Expression? root, MemberIdentity memberIdentity) { + if (root == null) + { + return null; + } + var innerExpression = root.UnwrapTypeConversion(out var convertedType); if (UnwrapEntityReference(innerExpression) is EntityReference entityReference) { @@ -163,7 +169,7 @@ protected Expression ExpandNavigation( ownedExpansion = new OwnedNavigationReference(root, navigation, ownedEntityReference); if (navigation.IsCollection) { - var elementType = ownedExpansion.Type.TryGetSequenceType(); + var elementType = ownedExpansion.Type.GetSequenceType(); var subquery = Expression.Call( QueryableMethods.AsQueryable.MakeGenericMethod(elementType), ownedExpansion); @@ -431,13 +437,14 @@ outerKey is NewArrayExpression newArrayExpression var resultSelectorInnerParameter = Expression.Parameter(innerSource.SourceElementType, "i"); var resultType = TransparentIdentifierFactory.Create(_source.SourceElementType, innerSource.SourceElementType); - var transparentIdentifierOuterMemberInfo = resultType.GetTypeInfo().GetDeclaredField("Outer"); - var transparentIdentifierInnerMemberInfo = resultType.GetTypeInfo().GetDeclaredField("Inner"); + var transparentIdentifierOuterMemberInfo = resultType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var transparentIdentifierInnerMemberInfo = resultType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var resultSelector = Expression.Lambda( Expression.New( resultType.GetConstructors().Single(), - new[] { resultSelectorOuterParameter, resultSelectorInnerParameter }, transparentIdentifierOuterMemberInfo, + new[] { resultSelectorOuterParameter, resultSelectorInnerParameter }, + transparentIdentifierOuterMemberInfo, transparentIdentifierInnerMemberInfo), resultSelectorOuterParameter, resultSelectorInnerParameter); @@ -487,7 +494,7 @@ private static Expression AddConvertToObject(Expression expression) private sealed class IncludeExpandingExpressionVisitor : ExpandingExpressionVisitor { private static readonly MethodInfo _fetchJoinEntityMethodInfo = - typeof(IncludeExpandingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(FetchJoinEntity)); + typeof(IncludeExpandingExpressionVisitor).GetRequiredDeclaredMethod(nameof(FetchJoinEntity)); private readonly bool _queryStateManager; private readonly bool _ignoreAutoIncludes; @@ -542,25 +549,28 @@ protected override Expression VisitMember(MemberExpression memberExpression) { Check.NotNull(memberExpression, nameof(memberExpression)); - var innerExpression = memberExpression.Expression.UnwrapTypeConversion(out var convertedType); - if (UnwrapEntityReference(innerExpression) is EntityReference entityReference) + if (memberExpression.Expression != null) { - // If it is mapped property then, it would get converted to a column so we don't need to expand includes. - var entityType = entityReference.EntityType; - if (convertedType != null) + var innerExpression = memberExpression.Expression.UnwrapTypeConversion(out var convertedType); + if (UnwrapEntityReference(innerExpression) is EntityReference entityReference) { - entityType = entityType.GetAllBaseTypes().Concat(entityType.GetDerivedTypesInclusive()) - .FirstOrDefault(et => et.ClrType == convertedType); - if (entityType == null) + // If it is mapped property then, it would get converted to a column so we don't need to expand includes. + var entityType = entityReference.EntityType; + if (convertedType != null) { - return base.VisitMember(memberExpression); + entityType = entityType.GetAllBaseTypes().Concat(entityType.GetDerivedTypesInclusive()) + .FirstOrDefault(et => et.ClrType == convertedType); + if (entityType == null) + { + return base.VisitMember(memberExpression); + } } - } - var property = entityType.FindProperty(memberExpression.Member); - if (property != null) - { - return memberExpression; + var property = entityType.FindProperty(memberExpression.Member); + if (property != null) + { + return memberExpression; + } } } @@ -627,7 +637,7 @@ private bool ReconstructAnonymousType( for (var i = 0; i < newExpression.Arguments.Count; i++) { var argument = newExpression.Arguments[i]; - var newRoot = Expression.MakeMemberAccess(currentRoot, newExpression.Members[i]); + var newRoot = Expression.MakeMemberAccess(currentRoot, newExpression.Members![i]); if (argument is EntityReference entityReference) { changed = true; @@ -704,7 +714,7 @@ private Expression ExpandIncludesHelper(Expression root, EntityReference entityR && entityReference.EntityType.IsAssignableFrom(navigationBase.DeclaringEntityType)) { converted = true; - convertedRoot = Expression.Convert(root, navigationBase.DeclaringEntityType.ClrType); + convertedRoot = Expression.Convert(root, navigationBase.DeclaringEntityType.ClrType!); } var included = navigationBase switch @@ -774,14 +784,15 @@ private Expression ExpandIncludesHelper(Expression root, EntityReference entityR targetParameter)); subquery = joinMethodCallExpression.Update( - null, joinMethodCallExpression.Arguments.Take(4).Append(newResultSelector)); + // TODO-Nullable bug + null!, joinMethodCallExpression.Arguments.Take(4).Append(newResultSelector)); } else { var resultType = TransparentIdentifierFactory.Create(joinParameter.Type, targetParameter.Type); - var transparentIdentifierOuterMemberInfo = resultType.GetTypeInfo().GetDeclaredField("Outer"); - var transparentIdentifierInnerMemberInfo = resultType.GetTypeInfo().GetDeclaredField("Inner"); + var transparentIdentifierOuterMemberInfo = resultType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var transparentIdentifierInnerMemberInfo = resultType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var newResultSelector = Expression.Quote( Expression.Lambda( @@ -896,7 +907,8 @@ public PendingSelectorExpandingExpressionVisitor( _applyIncludes = applyIncludes; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { if (expression is NavigationExpansionExpression navigationExpansionExpression) { @@ -921,7 +933,8 @@ public override Expression Visit(Expression expression) /// private sealed class ReducingExpressionVisitor : ExpressionVisitor { - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { switch (expression) { @@ -954,7 +967,7 @@ public override Expression Visit(Expression expression) { result = Expression.Call( navigationExpansionExpression.CardinalityReducingGenericMethodInfo.MakeGenericMethod( - result.Type.TryGetSequenceType()), + result.Type.GetSequenceType()), result); } @@ -988,7 +1001,8 @@ public override Expression Visit(Expression expression) /// private sealed class EntityReferenceOptionalMarkingExpressionVisitor : ExpressionVisitor { - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { if (expression is EntityReference entityReference) { @@ -1130,7 +1144,8 @@ private Expression ProcessNavigationPath(Expression expression) { switch (expression) { - case MemberExpression memberExpression: + case MemberExpression memberExpression + when memberExpression.Expression != null: var innerExpression = ProcessNavigationPath(memberExpression.Expression); if (innerExpression is NavigationDataExpression navigationDataExpression && navigationDataExpression.EntityType != null) diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs index cc0a59537ce..f9724a98f4f 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs @@ -13,6 +13,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -27,9 +28,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal public partial class NavigationExpandingExpressionVisitor : ExpressionVisitor { private static readonly PropertyInfo _queryContextContextPropertyInfo - = typeof(QueryContext) - .GetTypeInfo() - .GetDeclaredProperty(nameof(QueryContext.Context)); + = typeof(QueryContext).GetRequiredDeclaredProperty(nameof(QueryContext.Context)); private static readonly Dictionary _predicateLessMethodInfo = new Dictionary { @@ -125,7 +124,7 @@ public virtual Expression Expand([NotNull] Expression query) foreach (var parameterValue in _parameters.ParameterValues) { - var lambda = (LambdaExpression)parameterValue.Value; + var lambda = (LambdaExpression)parameterValue.Value!; var remappedLambdaBody = ReplacingExpressionVisitor.Replace( lambda.Parameters[0], dbContextOnQueryContextPropertyAccess, @@ -206,6 +205,7 @@ protected override Expression VisitMember(MemberExpression memberExpression) // Convert ICollection.Count to Count() if (memberExpression.Expression != null + && innerExpression != null && memberExpression.Member.Name == nameof(ICollection.Count) && memberExpression.Expression.Type.GetInterfaces().Append(memberExpression.Expression.Type) .Any(e => e.IsGenericType && e.GetGenericTypeDefinition() == typeof(ICollection<>))) @@ -216,7 +216,7 @@ protected override Expression VisitMember(MemberExpression memberExpression) { return Visit( Expression.Call( - QueryableMethods.CountWithoutPredicate.MakeGenericMethod(innerQueryable.Type.TryGetSequenceType()), + QueryableMethods.CountWithoutPredicate.MakeGenericMethod(innerQueryable.Type.GetSequenceType()), innerQueryable)); } } @@ -255,7 +255,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp || method.DeclaringType == typeof(EntityFrameworkQueryableExtensions)) { var genericMethod = method.IsGenericMethod ? method.GetGenericMethodDefinition() : null; - var firstArgument = Visit(methodCallExpression.Arguments[0]); + // First argument is source + var firstArgument = Visit(methodCallExpression.Arguments[0])!; if (firstArgument is NavigationExpansionExpression source) { if (source.PendingOrderings.Any() @@ -454,8 +455,7 @@ when QueryableMethods.IsSumWithSelector(method): return ProcessCastOfType( source, genericMethod, - // Known to be sequence type - methodCallExpression.Type.TryGetSequenceType()!); + methodCallExpression.Type.GetSequenceType()); case nameof(EntityFrameworkQueryableExtensions.Include): case nameof(EntityFrameworkQueryableExtensions.ThenInclude): @@ -562,8 +562,8 @@ when QueryableMethods.IsSumWithSelector(method): if (firstArgument.Type.TryGetElementType(typeof(IQueryable<>)) == null) { // firstArgument was not an queryable - var visitedArguments = new[] { firstArgument } - .Concat(methodCallExpression.Arguments.Skip(1).Select(Visit)); + var visitedArguments = new [] { firstArgument } + .Concat(methodCallExpression.Arguments.Skip(1).Select(e => Visit(e)!)); return ConvertToEnumerable(method, visitedArguments); } @@ -577,7 +577,8 @@ when QueryableMethods.IsSumWithSelector(method): || method.GetGenericMethodDefinition() == EnumerableMethods.ToArray)) { return methodCallExpression.Update( - null, new[] { UnwrapCollectionMaterialization(Visit(methodCallExpression.Arguments[0])) }); + // TODO-Nullable bug + null!, new[] { UnwrapCollectionMaterialization(Visit(methodCallExpression.Arguments[0])) }); } return ProcessUnknownMethod(methodCallExpression); @@ -650,7 +651,7 @@ private Expression ProcessAverageMaxMinSum(NavigationExpansionExpression source, if (method.GetGenericArguments().Length == 1) { // Min/Max without selector has 1 generic parameters - method = method.MakeGenericMethod(queryable.Type.TryGetSequenceType()); + method = method.MakeGenericMethod(queryable.Type.GetSequenceType()); } return Expression.Call(method, queryable); @@ -715,7 +716,7 @@ private Expression ProcessContains(NavigationExpansionExpression source, Express source = (NavigationExpansionExpression)_pendingSelectorExpandingExpressionVisitor.Visit(source); var queryable = Reduce(source); - return Expression.Call(QueryableMethods.Contains.MakeGenericMethod(queryable.Type.TryGetSequenceType()), queryable, item); + return Expression.Call(QueryableMethods.Contains.MakeGenericMethod(queryable.Type.GetSequenceType()), queryable, item); } private NavigationExpansionExpression ProcessDefaultIfEmpty(NavigationExpansionExpression source) @@ -745,7 +746,7 @@ private NavigationExpansionExpression ProcessDistinct(NavigationExpansionExpress var newStructure = SnapshotExpression(source.PendingSelector); var queryable = Reduce(source); - var result = Expression.Call(genericMethod.MakeGenericMethod(queryable.Type.TryGetSequenceType()), queryable); + var result = Expression.Call(genericMethod.MakeGenericMethod(queryable.Type.GetSequenceType()), queryable); var navigationTree = new NavigationTreeExpression(newStructure); var parameterName = GetParameterName("e"); @@ -820,7 +821,7 @@ private NavigationExpansionExpression ProcessGroupBy( Expression.Quote(elementSelector), Expression.Quote(Visit(resultSelector))); - var navigationTree = new NavigationTreeExpression(Expression.Default(result.Type.TryGetSequenceType())); + var navigationTree = new NavigationTreeExpression(Expression.Default(result.Type.GetSequenceType())); var parameterName = GetParameterName("e"); return new NavigationExpansionExpression(result, navigationTree, navigationTree, parameterName); @@ -928,7 +929,8 @@ private NavigationExpansionExpression ProcessInclude(NavigationExpansionExpressi var arguments = new List { filterExpression.Body }; arguments.AddRange(methodCallExpression.Arguments.Skip(1)); filterExpression = Expression.Lambda( - methodCallExpression.Update(methodCallExpression.Object, arguments), + // TODO-Nullable bug + methodCallExpression.Update(methodCallExpression.Object!, arguments), filterExpression.Parameters); return (result, filterExpression); @@ -953,7 +955,8 @@ static Expression FormatFilter(Expression expression) arguments.Add(source); arguments.AddRange(methodCallExpression.Arguments.Skip(1)); - return methodCallExpression.Update(methodCallExpression.Object, arguments); + // TODO-Nullable bug + return methodCallExpression.Update(methodCallExpression.Object!, arguments); } return expression; @@ -977,8 +980,8 @@ private NavigationExpansionExpression ProcessJoin( var transparentIdentifierType = TransparentIdentifierFactory.Create( outerSource.SourceElementType, innerSource.SourceElementType); - var transparentIdentifierOuterMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var transparentIdentifierInnerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var transparentIdentifierOuterMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var transparentIdentifierInnerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var newResultSelector = Expression.Lambda( Expression.New( @@ -1026,8 +1029,8 @@ private NavigationExpansionExpression ProcessLeftJoin( var transparentIdentifierType = TransparentIdentifierFactory.Create( outerSource.SourceElementType, innerSource.SourceElementType); - var transparentIdentifierOuterMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var transparentIdentifierInnerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var transparentIdentifierOuterMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var transparentIdentifierInnerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var newResultSelector = Expression.Lambda( Expression.New( @@ -1140,8 +1143,7 @@ private NavigationExpansionExpression ProcessSelectMany( collectionSource = (NavigationExpansionExpression)_pendingSelectorExpandingExpressionVisitor.Visit(collectionSource); var innerTree = new NavigationTreeExpression(SnapshotExpression(collectionSource.PendingSelector)); collectionSelector = GenerateLambda(collectionSource, source.CurrentParameter); - // Known to be sequence type - var collectionElementType = collectionSelector.ReturnType.TryGetSequenceType()!; + var collectionElementType = collectionSelector.ReturnType.GetSequenceType(); // Collection selector body is IQueryable, we need to adjust the type to IEnumerable, to match the SelectMany signature // therefore the delegate type is specified explicitly @@ -1156,8 +1158,8 @@ private NavigationExpansionExpression ProcessSelectMany( var transparentIdentifierType = TransparentIdentifierFactory.Create( source.SourceElementType, collectionElementType); - var transparentIdentifierOuterMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var transparentIdentifierInnerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var transparentIdentifierOuterMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var transparentIdentifierInnerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); var collectionElementParameter = Expression.Parameter(collectionElementType, "c"); var newResultSelector = Expression.Lambda( @@ -1210,9 +1212,8 @@ private NavigationExpansionExpression ProcessSetOperation( var outerQueryable = Reduce(outerSource); var innerQueryable = Reduce(innerSource); - // Known to be sequence type - var outerType = outerQueryable.Type.TryGetSequenceType()!; - var innerType = innerQueryable.Type.TryGetSequenceType()!; + var outerType = outerQueryable.Type.GetSequenceType(); + var innerType = innerQueryable.Type.GetSequenceType(); var result = Expression.Call( genericMethod.MakeGenericMethod(outerType.IsAssignableFrom(innerType) ? outerType : innerType), @@ -1411,7 +1412,7 @@ private Expression ApplyQueryFilter(IEntityType entityType, NavigationExpansionE // We need to do entity equality, but that requires a full method call on a query root to properly flow the // entity information through. Construct a MethodCall wrapper for the predicate with the proper query root. var filterWrapper = Expression.Call( - QueryableMethods.Where.MakeGenericMethod(rootEntityType.ClrType), + QueryableMethods.Where.MakeGenericMethod(rootEntityType.ClrType!), new QueryRootExpression(rootEntityType), filterPredicate); filterPredicate = filterWrapper.Arguments[1].UnwrapLambdaFromQuote(); @@ -1700,7 +1701,7 @@ private Expression UnwrapCollectionMaterialization(Expression expression) && ownedNavigationReference.Navigation.IsCollection ? CreateNavigationExpansionExpression( Expression.Call( - QueryableMethods.AsQueryable.MakeGenericMethod(ownedNavigationReference.Type.TryGetSequenceType()), + QueryableMethods.AsQueryable.MakeGenericMethod(ownedNavigationReference.Type.GetSequenceType()), ownedNavigationReference), ownedNavigationReference) : expression; @@ -1792,7 +1793,8 @@ private IncludeTreeNode PopulateIncludeTree(IncludeTreeNode includeTreeNode, Exp case ParameterExpression _: return includeTreeNode; - case MemberExpression memberExpression: + case MemberExpression memberExpression + when memberExpression.Expression != null: var innerExpression = memberExpression.Expression.UnwrapTypeConversion(out var convertedType); var innerIncludeTreeNode = PopulateIncludeTree(includeTreeNode, innerExpression); var entityType = innerIncludeTreeNode.EntityType; @@ -1871,7 +1873,7 @@ private Expression SnapshotExpression(Expression selector) } } - private static EntityReference? UnwrapEntityReference(Expression expression) + private static EntityReference? UnwrapEntityReference(Expression? expression) { switch (expression) { @@ -1895,12 +1897,12 @@ private Expression SnapshotExpression(Expression selector) private sealed class Parameters : IParameterValues { - private readonly IDictionary _parameterValues = new Dictionary(); + private readonly IDictionary _parameterValues = new Dictionary(); - public IReadOnlyDictionary ParameterValues - => (IReadOnlyDictionary)_parameterValues; + public IReadOnlyDictionary ParameterValues + => (IReadOnlyDictionary)_parameterValues; - public void AddParameter(string name, object value) + public void AddParameter(string name, object? value) { _parameterValues.Add(name, value); } diff --git a/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs index afdc6662bbc..0d32a09a6c0 100644 --- a/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs @@ -140,7 +140,8 @@ protected override Expression VisitMember(MemberExpression memberExpression) Check.NotNull(memberExpression, nameof(memberExpression)); var innerExpression = Visit(memberExpression.Expression); - if (_nullSafeAccesses.Contains(innerExpression)) + if (innerExpression != null + && _nullSafeAccesses.Contains(innerExpression)) { _nullSafeAccesses.Add(memberExpression); } diff --git a/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs b/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs index 76f2801bd9f..80650ae92a6 100644 --- a/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs @@ -270,7 +270,7 @@ protected override Expression VisitExtension(Expression extensionExpression) return base.VisitExtension(extensionExpression); } - private static Expression GenerateConstantExpression(object value, Type returnType) + private static Expression GenerateConstantExpression(object? value, Type returnType) { var constantExpression = Expression.Constant(value, value?.GetType() ?? returnType); @@ -355,7 +355,8 @@ public ContextParameterReplacingExpressionVisitor(Type contextType) public ParameterExpression ContextParameterExpression { get; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) => expression?.Type != typeof(object) && expression?.Type.IsAssignableFrom(_contextType) == true ? ContextParameterExpression @@ -374,7 +375,6 @@ private static Expression RemoveConvert(Expression expression) return expression; } - [return: CA.NotNullIfNotNull("expression")] private object? GetValue(Expression? expression, out string? parameterName) { parameterName = null; @@ -498,7 +498,8 @@ public IDictionary Find(Expression expression) return _evaluatableExpressions; } - public override Expression Visit(Expression expression) + [return: CA.NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { if (expression == null) { diff --git a/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs b/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs index 5c9b8dcb595..5536ea6ed51 100644 --- a/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs @@ -21,16 +21,16 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal public class QueryOptimizingExpressionVisitor : ExpressionVisitor { private static readonly MethodInfo _stringCompareWithComparisonMethod = - typeof(string).GetRuntimeMethod(nameof(string.Compare), new[] { typeof(string), typeof(string), typeof(StringComparison) }); + typeof(string).GetRequiredRuntimeMethod(nameof(string.Compare), new[] { typeof(string), typeof(string), typeof(StringComparison) }); private static readonly MethodInfo _stringCompareWithoutComparisonMethod = - typeof(string).GetRuntimeMethod(nameof(string.Compare), new[] { typeof(string), typeof(string) }); + typeof(string).GetRequiredRuntimeMethod(nameof(string.Compare), new[] { typeof(string), typeof(string) }); private static readonly MethodInfo _startsWithMethodInfo = - typeof(string).GetRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); + typeof(string).GetRequiredRuntimeMethod(nameof(string.StartsWith), new[] { typeof(string) }); private static readonly MethodInfo _endsWithMethodInfo = - typeof(string).GetRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); + typeof(string).GetRequiredRuntimeMethod(nameof(string.EndsWith), new[] { typeof(string) }); private static readonly Expression _constantNullString = Expression.Constant(null, typeof(string)); @@ -57,17 +57,18 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); - if (_startsWithMethodInfo.Equals(methodCallExpression.Method) - || _endsWithMethodInfo.Equals(methodCallExpression.Method)) + if (Equals(_startsWithMethodInfo, methodCallExpression.Method) + || Equals(_endsWithMethodInfo, methodCallExpression.Method)) { if (methodCallExpression.Arguments[0] is ConstantExpression constantArgument - && (string)constantArgument.Value == string.Empty) + && constantArgument.Value is string stringValue + && stringValue == string.Empty) { // every string starts/ends with empty string. return Expression.Constant(true); } - var newObject = Visit(methodCallExpression.Object); + var newObject = Visit(methodCallExpression.Object)!; var newArgument = Visit(methodCallExpression.Arguments[0]); var result = Expression.AndAlso( @@ -136,9 +137,12 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp && visited.Method.DeclaringType?.Namespace == "Microsoft.VisualBasic.CompilerServices" && visited.Object == null && visited.Arguments.Count == 3 - && visited.Arguments[2] is ConstantExpression textCompareConstantExpression) + && visited.Arguments[2] is ConstantExpression textCompareConstantExpression + && _stringCompareWithComparisonMethod != null + && _stringCompareWithoutComparisonMethod != null) { - return (bool)textCompareConstantExpression.Value + return textCompareConstantExpression.Value is bool boolValue + && boolValue ? Expression.Call( _stringCompareWithComparisonMethod, visited.Arguments[0], @@ -165,17 +169,18 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) if (unaryExpression.NodeType == ExpressionType.Not && unaryExpression.Operand is MethodCallExpression innerMethodCall - && (_startsWithMethodInfo.Equals(innerMethodCall.Method) - || _endsWithMethodInfo.Equals(innerMethodCall.Method))) + && (Equals(_startsWithMethodInfo, innerMethodCall.Method) + || Equals(_endsWithMethodInfo, innerMethodCall.Method))) { if (innerMethodCall.Arguments[0] is ConstantExpression constantArgument - && (string)constantArgument.Value == string.Empty) + && constantArgument.Value is string stringValue + && stringValue == string.Empty) { // every string starts/ends with empty string. return Expression.Constant(false); } - var newObject = Visit(innerMethodCall.Object); + var newObject = Visit(innerMethodCall.Object)!; var newArgument = Visit(innerMethodCall.Arguments[0]); var result = Expression.AndAlso( @@ -227,7 +232,7 @@ private bool TryExtractEqualityOperands( { negated = false; if (methodCallExpression.Arguments.Count == 1 - && methodCallExpression.Object.Type == methodCallExpression.Arguments[0].Type) + && methodCallExpression.Object?.Type == methodCallExpression.Arguments[0].Type) { (left, right) = (methodCallExpression.Object, methodCallExpression.Arguments[0]); diff --git a/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs b/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs index 42e458f962a..971c4b44f06 100644 --- a/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs @@ -69,10 +69,11 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp visitedExpression = TryConvertEnumerableToQueryable(methodCallExpression); } - if (methodCallExpression.Method.DeclaringType.IsGenericType - && (methodCallExpression.Method.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>) - || methodCallExpression.Method.DeclaringType.GetGenericTypeDefinition() == typeof(List<>)) - && methodCallExpression.Method.Name == nameof(List.Contains)) + if (method.DeclaringType != null + && method.DeclaringType.IsGenericType + && (method.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>) + || method.DeclaringType.GetGenericTypeDefinition() == typeof(List<>)) + && method.Name == nameof(List.Contains)) { visitedExpression = TryConvertListContainsToQueryableContains(methodCallExpression); } @@ -111,7 +112,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return Expression.Call(newIncludeMethod, source, lambda); } - return methodCallExpression.Update(null, new[] { source, lambda }); + // TODO-Nullable bug + return methodCallExpression.Update(null!, new[] { source, lambda }); } } @@ -207,7 +209,7 @@ private void VerifyReturnType(Expression expression, ParameterExpression lambdaP if (genericMethodDefinition == EntityFrameworkQueryableExtensions.TagWithMethodInfo) { var visitedExpression = Visit(methodCallExpression.Arguments[0]); - _queryCompilationContext.AddTag((string)((ConstantExpression)methodCallExpression.Arguments[1]).Value); + _queryCompilationContext.AddTag(methodCallExpression.Arguments[1].GetConstantValue()); return visitedExpression; } @@ -318,7 +320,7 @@ private Expression TryConvertEnumerableToQueryable(MethodCallExpression methodCa if (CanConvertEnumerableToQueryable(enumerableParameterType, queryableParameterType)) { var innerArgument = arguments[i]; - var genericType = innerArgument.Type.TryGetSequenceType(); + var genericType = innerArgument.Type.GetSequenceType(); // If innerArgument has ToList applied to it then unwrap it. // Also preserve generic argument of ToList is applied to different type @@ -363,7 +365,8 @@ private Expression TryConvertEnumerableToQueryable(MethodCallExpression methodCa } } - return methodCallExpression.Update(Visit(methodCallExpression.Object), arguments); + // TODO-Nullable bug + return methodCallExpression.Update(Visit(methodCallExpression.Object)!, arguments); } private Expression TryConvertListContainsToQueryableContains(MethodCallExpression methodCallExpression) @@ -374,17 +377,17 @@ private Expression TryConvertListContainsToQueryableContains(MethodCallExpressio return base.VisitMethodCall(methodCallExpression); } - var sourceType = methodCallExpression.Method.DeclaringType.GetGenericArguments()[0]; + var sourceType = methodCallExpression.Method.DeclaringType!.GetGenericArguments()[0]; return Expression.Call( QueryableMethods.Contains.MakeGenericMethod(sourceType), Expression.Call( QueryableMethods.AsQueryable.MakeGenericMethod(sourceType), - methodCallExpression.Object), + methodCallExpression.Object!), methodCallExpression.Arguments[0]); } - private static bool ClientSource(Expression expression) + private static bool ClientSource(Expression? expression) => expression is ConstantExpression || expression is MemberInitExpression || expression is NewExpression @@ -486,8 +489,8 @@ private Expression TryFlattenGroupJoinSelectMany(MethodCallExpression methodCall // left join return Expression.Call( QueryableExtensions.LeftJoinMethodInfo.MakeGenericMethod( - outer.Type.TryGetSequenceType(), - inner.Type.TryGetSequenceType(), + outer.Type.GetSequenceType(), + inner.Type.GetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, @@ -500,8 +503,8 @@ private Expression TryFlattenGroupJoinSelectMany(MethodCallExpression methodCall // inner join return Expression.Call( QueryableMethods.Join.MakeGenericMethod( - outer.Type.TryGetSequenceType(), - inner.Type.TryGetSequenceType(), + outer.Type.GetSequenceType(), + inner.Type.GetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, @@ -520,7 +523,7 @@ private Expression TryFlattenGroupJoinSelectMany(MethodCallExpression methodCall // innerKeySelector.Body); // inner = Expression.Call( - // QueryableMethods.Where.MakeGenericMethod(inner.Type.TryGetSequenceType()), + // QueryableMethods.Where.MakeGenericMethod(inner.Type.GetSequenceType()), // inner, // Expression.Quote(Expression.Lambda(correlationPredicate, innerParameter))); @@ -600,8 +603,8 @@ private Expression TryFlattenGroupJoinSelectMany(MethodCallExpression methodCall // left join return Expression.Call( QueryableExtensions.LeftJoinMethodInfo.MakeGenericMethod( - outer.Type.TryGetSequenceType(), - inner.Type.TryGetSequenceType(), + outer.Type.GetSequenceType(), + inner.Type.GetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, @@ -614,8 +617,8 @@ private Expression TryFlattenGroupJoinSelectMany(MethodCallExpression methodCall // inner join return Expression.Call( QueryableMethods.Join.MakeGenericMethod( - outer.Type.TryGetSequenceType(), - inner.Type.TryGetSequenceType(), + outer.Type.GetSequenceType(), + inner.Type.GetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, diff --git a/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs b/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs index 9065b1ec957..70e15da3440 100644 --- a/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/SubqueryMemberPushdownExpressionVisitor.cs @@ -169,7 +169,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp var updatedMemberExpression = memberExpression.Update(Visit(memberExpression.Expression)); return Expression.Call( - QueryableMethods.AsQueryable.MakeGenericMethod(updatedMemberExpression.Type.TryGetSequenceType()), + QueryableMethods.AsQueryable.MakeGenericMethod(updatedMemberExpression.Type.GetSequenceType()), updatedMemberExpression); } @@ -182,7 +182,7 @@ private Expression PushdownMember( Type returnType) { var source = methodCallExpression.Arguments[0]; - var queryableType = source.Type.TryGetSequenceType(); + var queryableType = source.Type.GetSequenceType(); var genericMethod = methodCallExpression.Method.GetGenericMethodDefinition(); if (methodCallExpression.Arguments.Count == 2) { @@ -206,7 +206,7 @@ private Expression PushdownMember( source = Expression.Call( QueryableMethods.Select.MakeGenericMethod( - sourceMethodCallExpression.Arguments[0].Type.TryGetSequenceType(), memberAccessExpression.Type), + sourceMethodCallExpression.Arguments[0].Type.GetSequenceType(), memberAccessExpression.Type), sourceMethodCallExpression.Arguments[0], Expression.Quote(Expression.Lambda(memberAccessExpression, selector.Parameters[0]))); @@ -224,7 +224,7 @@ private Expression PushdownMember( Expression.Quote(Expression.Lambda(memberAccessExpression, parameter))); } - source = Expression.Call(genericMethod.MakeGenericMethod(source.Type.TryGetSequenceType()), source); + source = Expression.Call(genericMethod.MakeGenericMethod(source.Type.GetSequenceType()), source); return source.Type != returnType ? Expression.Convert(source, returnType) diff --git a/src/EFCore/Query/ProjectionBindingExpression.cs b/src/EFCore/Query/ProjectionBindingExpression.cs index 94a5fab35d9..617736a46ce 100644 --- a/src/EFCore/Query/ProjectionBindingExpression.cs +++ b/src/EFCore/Query/ProjectionBindingExpression.cs @@ -128,7 +128,7 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) } else if (Index != null) { - expressionPrinter.Append(Index.ToString()); + expressionPrinter.Append(Index.ToString()!); } else if (IndexMap != null) { diff --git a/src/EFCore/Query/ProjectionMember.cs b/src/EFCore/Query/ProjectionMember.cs index d2a130ac248..44c9a2e469f 100644 --- a/src/EFCore/Query/ProjectionMember.cs +++ b/src/EFCore/Query/ProjectionMember.cs @@ -80,7 +80,7 @@ public ProjectionMember Prepend([NotNull] MemberInfo member) /// This method is generally used to get last memberInfo to generate an alias for projection. /// /// - public MemberInfo Last + public MemberInfo? Last => _memberChain.LastOrDefault(); /// diff --git a/src/EFCore/Query/QueryCompilationContext.cs b/src/EFCore/Query/QueryCompilationContext.cs index ba57ca4542a..913b4a2d2c2 100644 --- a/src/EFCore/Query/QueryCompilationContext.cs +++ b/src/EFCore/Query/QueryCompilationContext.cs @@ -49,6 +49,17 @@ public class QueryCompilationContext /// public static readonly ParameterExpression QueryContextParameter = Expression.Parameter(typeof(QueryContext), "queryContext"); + /// + /// + /// Expression representing a not translated expression in query tree during translation phase. + /// + /// + /// This property is typically used by database providers (and other extensions). It is generally + /// not used in application code. + /// + /// + public static readonly Expression NotTranslatedExpression = new NotTranslatedExpressionType(); + private readonly IQueryTranslationPreprocessorFactory _queryTranslationPreprocessorFactory; private readonly IQueryableMethodTranslatingExpressionVisitorFactory _queryableMethodTranslatingExpressionVisitorFactory; private readonly IQueryTranslationPostprocessorFactory _queryTranslationPostprocessorFactory; @@ -238,8 +249,12 @@ private Expression InsertRuntimeParameters(Expression query) .Append(query)); private static readonly MethodInfo _queryContextAddParameterMethodInfo - = typeof(QueryContext) - .GetTypeInfo() - .GetDeclaredMethod(nameof(QueryContext.AddParameter)); + = typeof(QueryContext).GetRequiredDeclaredMethod(nameof(QueryContext.AddParameter)); + + private sealed class NotTranslatedExpressionType : Expression + { + public override Type Type => typeof(object); + public override ExpressionType NodeType => ExpressionType.Extension; + } } } diff --git a/src/EFCore/Query/QueryContext.cs b/src/EFCore/Query/QueryContext.cs index 9568ebfe42b..647bf118578 100644 --- a/src/EFCore/Query/QueryContext.cs +++ b/src/EFCore/Query/QueryContext.cs @@ -29,7 +29,7 @@ namespace Microsoft.EntityFrameworkCore.Query /// public abstract class QueryContext : IParameterValues { - private readonly IDictionary _parameterValues = new Dictionary(); + private readonly IDictionary _parameterValues = new Dictionary(); private IStateManager? _stateManager; /// @@ -114,15 +114,15 @@ public virtual IDiagnosticsLogger QueryLogger /// /// The parameter values to use while executing the query. /// - public virtual IReadOnlyDictionary ParameterValues - => (IReadOnlyDictionary)_parameterValues; + public virtual IReadOnlyDictionary ParameterValues + => (IReadOnlyDictionary)_parameterValues; /// /// Adds a parameter to for this query. /// /// The name. /// The value. - public virtual void AddParameter(string name, object value) + public virtual void AddParameter(string name, object? value) { Check.NotEmpty(name, nameof(name)); diff --git a/src/EFCore/Query/QueryRootExpression.cs b/src/EFCore/Query/QueryRootExpression.cs index 00fbf6201fb..f8efa45dcc4 100644 --- a/src/EFCore/Query/QueryRootExpression.cs +++ b/src/EFCore/Query/QueryRootExpression.cs @@ -36,7 +36,7 @@ public QueryRootExpression([NotNull] IAsyncQueryProvider asyncQueryProvider, [No QueryProvider = asyncQueryProvider; EntityType = entityType; - Type = typeof(IQueryable<>).MakeGenericType(entityType.ClrType); + Type = typeof(IQueryable<>).MakeGenericType(entityType.ClrType!); } /// @@ -49,7 +49,7 @@ public QueryRootExpression([NotNull] IEntityType entityType) EntityType = entityType; QueryProvider = null; - Type = typeof(IQueryable<>).MakeGenericType(entityType.ClrType); + Type = typeof(IQueryable<>).MakeGenericType(entityType.ClrType!); } /// diff --git a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs index de17d177875..f51fa869eb5 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)); @@ -98,7 +98,7 @@ protected virtual void AddTranslationErrorDetails([NotNull] string details) } /// - protected override Expression? VisitMethodCall(MethodCallExpression methodCallExpression) + protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { Check.NotNull(methodCallExpression, nameof(methodCallExpression)); @@ -163,9 +163,9 @@ when QueryableMethods.IsAverageWithSelector(method): var source2 = Visit(methodCallExpression.Arguments[1]); if (source2 is ShapedQueryExpression innerShapedQueryExpression) { - return TranslateConcat( + return CheckTranslated(TranslateConcat( shapedQueryExpression, - innerShapedQueryExpression); + innerShapedQueryExpression)); } break; @@ -495,7 +495,7 @@ LambdaExpression GetLambdaExpressionFromArgument(int argumentIndex) } return _subquery - ? (Expression?)null + ? QueryCompilationContext.NotTranslatedExpression : throw new InvalidOperationException(CoreStrings.TranslationFailed(methodCallExpression.Print())); } @@ -571,8 +571,8 @@ private Expression CombineShapers( Expression innerShaper, Type transparentIdentifierType) { - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); + var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); outerShaper = new MemberAccessShiftingExpressionVisitor(queryExpression, outerMemberInfo).Visit(outerShaper); innerShaper = new MemberAccessShiftingExpressionVisitor(queryExpression, innerMemberInfo).Visit(innerShaper); @@ -612,7 +612,7 @@ private static Expression AccessOuterTransparentField( Type transparentIdentifierType, Expression targetExpression) { - var fieldInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); + var fieldInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); return Expression.Field(targetExpression, fieldInfo); } @@ -622,7 +622,7 @@ private static Expression AccessInnerTransparentField( Type transparentIdentifierType, Expression targetExpression) { - var fieldInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var fieldInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); return Expression.Field(targetExpression, fieldInfo); } @@ -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. diff --git a/src/EFCore/Query/ReplacingExpressionVisitor.cs b/src/EFCore/Query/ReplacingExpressionVisitor.cs index d8c2d281ff1..d3433df558d 100644 --- a/src/EFCore/Query/ReplacingExpressionVisitor.cs +++ b/src/EFCore/Query/ReplacingExpressionVisitor.cs @@ -140,7 +140,8 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return memberAssignment.Expression; } - return methodCallExpression.Update(null, new[] { newEntityExpression, methodCallExpression.Arguments[1] }); + // TODO-Nullable bug + return methodCallExpression.Update(null!, new[] { newEntityExpression, methodCallExpression.Arguments[1] }); } return base.VisitMethodCall(methodCallExpression); diff --git a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs index e277e16c3f7..5ccd52910d0 100644 --- a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs @@ -41,9 +41,9 @@ namespace Microsoft.EntityFrameworkCore.Query public abstract class ShapedQueryCompilingExpressionVisitor : ExpressionVisitor { private static readonly PropertyInfo _cancellationTokenMemberInfo - = typeof(QueryContext).GetProperty(nameof(QueryContext.CancellationToken)); + = typeof(QueryContext).GetRequiredProperty(nameof(QueryContext.CancellationToken)); - private readonly Expression? _cancellationTokenParameter; + private readonly Expression _cancellationTokenParameter; private readonly EntityMaterializerInjectingExpressionVisitor _entityMaterializerInjectingExpressionVisitor; private readonly ConstantVerifyingExpressionVisitor _constantVerifyingExpressionVisitor; @@ -75,6 +75,10 @@ protected ShapedQueryCompilingExpressionVisitor( QueryCompilationContext.QueryContextParameter, _cancellationTokenMemberInfo); } + else + { + _cancellationTokenParameter = null!; + } } /// @@ -103,22 +107,22 @@ protected override Expression VisitExtension(Expression extensionExpression) case ResultCardinality.Single: return QueryCompilationContext.IsAsync ? Expression.Call( - _singleAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.TryGetSequenceType()), + _singleAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()), serverEnumerable, _cancellationTokenParameter) : Expression.Call( - EnumerableMethods.SingleWithoutPredicate.MakeGenericMethod(serverEnumerable.Type.TryGetSequenceType()), + EnumerableMethods.SingleWithoutPredicate.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()), serverEnumerable); case ResultCardinality.SingleOrDefault: return QueryCompilationContext.IsAsync ? Expression.Call( - _singleOrDefaultAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.TryGetSequenceType()), + _singleOrDefaultAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.GetSequenceType()), serverEnumerable, _cancellationTokenParameter) : Expression.Call( EnumerableMethods.SingleOrDefaultWithoutPredicate.MakeGenericMethod( - serverEnumerable.Type.TryGetSequenceType()), + serverEnumerable.Type.GetSequenceType()), serverEnumerable); } } @@ -301,20 +305,20 @@ private static readonly ConstructorInfo _valueBufferConstructor = typeof(ValueBuffer).GetTypeInfo().DeclaredConstructors.Single(ci => ci.GetParameters().Length == 1); private static readonly PropertyInfo _dbContextMemberInfo - = typeof(QueryContext).GetProperty(nameof(QueryContext.Context)); + = typeof(QueryContext).GetRequiredProperty(nameof(QueryContext.Context)); private static readonly PropertyInfo _entityMemberInfo - = typeof(InternalEntityEntry).GetProperty(nameof(InternalEntityEntry.Entity)); + = typeof(InternalEntityEntry).GetRequiredProperty(nameof(InternalEntityEntry.Entity)); private static readonly PropertyInfo _entityTypeMemberInfo - = typeof(InternalEntityEntry).GetProperty(nameof(InternalEntityEntry.EntityType)); + = typeof(InternalEntityEntry).GetRequiredProperty(nameof(InternalEntityEntry.EntityType)); private static readonly MethodInfo _tryGetEntryMethodInfo = typeof(QueryContext).GetTypeInfo().GetDeclaredMethods(nameof(QueryContext.TryGetEntry)) .Single(mi => mi.GetParameters().Length == 4); private static readonly MethodInfo _startTrackingMethodInfo - = typeof(QueryContext).GetMethod( + = typeof(QueryContext).GetRequiredMethod( nameof(QueryContext.StartTracking), new[] { typeof(IEntityType), typeof(object), typeof(ValueBuffer) }); private readonly IEntityMaterializerSource _entityMaterializerSource; @@ -395,12 +399,12 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres "entityType" + _currentEntityIndex); variables.Add(concreteEntityTypeVariable); - var instanceVariable = Expression.Variable(entityType.ClrType, "instance" + _currentEntityIndex); + var instanceVariable = Expression.Variable(entityType.ClrType!, "instance" + _currentEntityIndex); variables.Add(instanceVariable); expressions.Add( Expression.Assign( instanceVariable, - Expression.Constant(null, entityType.ClrType))); + Expression.Constant(null, entityType.ClrType!))); if (_queryStateMananger && primaryKey != null) @@ -442,7 +446,7 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres Expression.Assign( instanceVariable, Expression.Convert( Expression.MakeMemberAccess(entryVariable, _entityMemberInfo), - entityType.ClrType))), + entityType.ClrType!))), MaterializeEntity( entityShaperExpression, materializationContextVariable, concreteEntityTypeVariable, instanceVariable, entryVariable)))); @@ -536,7 +540,7 @@ private Expression MaterializeEntity( expressions.Add( Expression.Assign( - entryVariable, + entryVariable!, Expression.Condition( Expression.Equal(concreteEntityTypeVariable, Expression.Default(typeof(IEntityType))), Expression.Default(typeof(InternalEntityEntry)), diff --git a/src/Shared/ExpressionExtensions.cs b/src/Shared/ExpressionExtensions.cs index 551ba80ef06..9587cec81ba 100644 --- a/src/Shared/ExpressionExtensions.cs +++ b/src/Shared/ExpressionExtensions.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using JetBrains.Annotations; +using CA = System.Diagnostics.CodeAnalysis; #nullable enable @@ -21,7 +22,8 @@ public static LambdaExpression UnwrapLambdaFromQuote(this Expression expression) ? unary.Operand : expression); - public static Expression UnwrapTypeConversion(this Expression expression, out Type? convertedType) + [return: CA.NotNullIfNotNull("expression")] + public static Expression? UnwrapTypeConversion(this Expression? expression, out Type? convertedType) { convertedType = null; while (expression is UnaryExpression unaryExpression @@ -51,5 +53,10 @@ private static Expression RemoveConvert(Expression expression) return expression; } + + public static T GetConstantValue(this Expression expression) + => expression is ConstantExpression constantExpression + ? (T)constantExpression.Value! + : throw new InvalidOperationException(); } } diff --git a/src/Shared/MemberInfoExtensions.cs b/src/Shared/MemberInfoExtensions.cs index eadbe488495..046e6fe66b7 100644 --- a/src/Shared/MemberInfoExtensions.cs +++ b/src/Shared/MemberInfoExtensions.cs @@ -5,7 +5,8 @@ namespace System.Reflection { - internal static class MemberInfoExtensions + internal static class EntityFrameworkMemberInfoExtensions + { public static Type GetMemberType(this MemberInfo memberInfo) => (memberInfo as PropertyInfo)?.PropertyType ?? ((FieldInfo)memberInfo)?.FieldType; diff --git a/src/Shared/SharedTypeExtensions.cs b/src/Shared/SharedTypeExtensions.cs index cc3b96a7ea0..a4b0253f9bc 100644 --- a/src/Shared/SharedTypeExtensions.cs +++ b/src/Shared/SharedTypeExtensions.cs @@ -10,6 +10,8 @@ using System.Text; using JetBrains.Annotations; +#nullable enable + // ReSharper disable once CheckNamespace namespace System { @@ -131,7 +133,7 @@ public static bool IsTupleType(this Type type) return false; } - public static PropertyInfo GetAnyProperty(this Type type, string name) + public static PropertyInfo? GetAnyProperty(this Type type, string name) { var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList(); if (props.Count > 1) @@ -142,6 +144,90 @@ public static PropertyInfo GetAnyProperty(this Type type, string name) return props.SingleOrDefault(); } + public static MethodInfo GetRequiredMethod(this Type type, string name, params Type[] parameters) + { + var method = type.GetTypeInfo().GetMethod(name, parameters); + + if (method == null + && parameters.Length == 0) + { + method = type.GetMethod(name); + } + + if (method == null) + { + throw new InvalidOperationException(); + } + + return method; + } + + public static PropertyInfo GetRequiredProperty(this Type type, string name) + { + var property = type.GetTypeInfo().GetProperty(name); + if (property == null) + { + throw new InvalidOperationException(); + } + + return property; + } + + public static FieldInfo GetRequiredDeclaredField(this Type type, string name) + { + var field = type.GetTypeInfo().GetDeclaredField(name); + if (field == null) + { + throw new InvalidOperationException(); + } + + return field; + } + + public static MethodInfo GetRequiredDeclaredMethod(this Type type, string name) + { + var method = type.GetTypeInfo().GetDeclaredMethod(name); + if (method == null) + { + throw new InvalidOperationException(); + } + + return method; + } + + public static PropertyInfo GetRequiredDeclaredProperty(this Type type, string name) + { + var property = type.GetTypeInfo().GetDeclaredProperty(name); + if (property == null) + { + throw new InvalidOperationException(); + } + + return property; + } + + public static MethodInfo GetRequiredRuntimeMethod(this Type type, string name, params Type[] parameters) + { + var method = type.GetTypeInfo().GetRuntimeMethod(name, parameters); + if (method == null) + { + throw new InvalidOperationException(); + } + + return method; + } + + public static PropertyInfo GetRequiredRuntimeProperty(this Type type, string name) + { + var property = type.GetTypeInfo().GetRuntimeProperty(name); + if (property == null) + { + throw new InvalidOperationException(); + } + + return property; + } + public static bool IsInstantiable(this Type type) => !type.IsAbstract && !type.IsInterface diff --git a/test/Directory.Build.props b/test/Directory.Build.props index c054a3fb4bd..86571cd8ba2 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,11 +1,6 @@ - - $(DefaultNetCoreTargetFramework) - $(StandardTestTfms);netcoreapp3.1 - - $(NoWarn);CA1707;1591;xUnit1000;xUnit1003;xUnit1004;xUnit1010;xUnit1013;xUnit1026 diff --git a/test/EFCore.Analyzers.Tests/EFCore.Analyzers.Tests.csproj b/test/EFCore.Analyzers.Tests/EFCore.Analyzers.Tests.csproj index 20045b2a73e..d68e8bdd40f 100644 --- a/test/EFCore.Analyzers.Tests/EFCore.Analyzers.Tests.csproj +++ b/test/EFCore.Analyzers.Tests/EFCore.Analyzers.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Analyzers.Tests Microsoft.EntityFrameworkCore true diff --git a/test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj b/test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj index 66cab175486..4476f37dc52 100644 --- a/test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj +++ b/test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj @@ -1,8 +1,7 @@  - $(StandardTestTfms) - $(DefaultNetCoreTargetFramework) + net5.0 Microsoft.EntityFrameworkCore.Cosmos.FunctionalTests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosDbConfiguredConditionAttribute.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosDbConfiguredConditionAttribute.cs index ca91b1850bf..ed75f2ebf2e 100644 --- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosDbConfiguredConditionAttribute.cs +++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosDbConfiguredConditionAttribute.cs @@ -2,16 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.IO; using System.Linq; using System.Net.Http; using System.Net.Sockets; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.TestUtilities.Xunit; -#if NET5_0 -using System.IO; -#endif - namespace Microsoft.EntityFrameworkCore.TestUtilities { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] @@ -71,12 +68,8 @@ private static async Task TryConnectAsync() private static bool IsNotConfigured(Exception exception) => exception switch { - HttpRequestException re => re.InnerException is SocketException -#if NET5_0 - || (re.InnerException is IOException networkException - && networkException.InnerException is SocketException) -#endif - , + HttpRequestException re => re.InnerException is SocketException // Exception in Mac/Linux + || (re.InnerException is IOException ioException && ioException.InnerException is SocketException), // Exception in Windows _ => exception.Message.Contains( "The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used.", StringComparison.Ordinal), diff --git a/test/EFCore.Cosmos.Tests/EFCore.Cosmos.Tests.csproj b/test/EFCore.Cosmos.Tests/EFCore.Cosmos.Tests.csproj index 8769167926a..092602ee0d0 100644 --- a/test/EFCore.Cosmos.Tests/EFCore.Cosmos.Tests.csproj +++ b/test/EFCore.Cosmos.Tests/EFCore.Cosmos.Tests.csproj @@ -1,8 +1,7 @@  - $(StandardTestTfms) - $(DefaultNetCoreTargetFramework) + net5.0 Microsoft.EntityFrameworkCore.Cosmos.Tests Microsoft.EntityFrameworkCore.Cosmos diff --git a/test/EFCore.CrossStore.FunctionalTests/EFCore.CrossStore.FunctionalTests.csproj b/test/EFCore.CrossStore.FunctionalTests/EFCore.CrossStore.FunctionalTests.csproj index 8c6c62cc11a..5be8fbf8d14 100644 --- a/test/EFCore.CrossStore.FunctionalTests/EFCore.CrossStore.FunctionalTests.csproj +++ b/test/EFCore.CrossStore.FunctionalTests/EFCore.CrossStore.FunctionalTests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.CrossStore.FunctionalTests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj b/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj index 78604fd4692..1f11db3b6ea 100644 --- a/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj +++ b/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 true Microsoft.EntityFrameworkCore.Design.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.InMemory.FunctionalTests/EFCore.InMemory.FunctionalTests.csproj b/test/EFCore.InMemory.FunctionalTests/EFCore.InMemory.FunctionalTests.csproj index e57c8fc8cb3..68ac9c2e3e2 100644 --- a/test/EFCore.InMemory.FunctionalTests/EFCore.InMemory.FunctionalTests.csproj +++ b/test/EFCore.InMemory.FunctionalTests/EFCore.InMemory.FunctionalTests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.InMemory.FunctionalTests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.InMemory.Tests/EFCore.InMemory.Tests.csproj b/test/EFCore.InMemory.Tests/EFCore.InMemory.Tests.csproj index a3507ee18e7..4281caef41e 100644 --- a/test/EFCore.InMemory.Tests/EFCore.InMemory.Tests.csproj +++ b/test/EFCore.InMemory.Tests/EFCore.InMemory.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.InMemory.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.OData.FunctionalTests/EFCore.OData.FunctionalTests.csproj b/test/EFCore.OData.FunctionalTests/EFCore.OData.FunctionalTests.csproj index 5565ed95691..9f4be8c8741 100644 --- a/test/EFCore.OData.FunctionalTests/EFCore.OData.FunctionalTests.csproj +++ b/test/EFCore.OData.FunctionalTests/EFCore.OData.FunctionalTests.csproj @@ -1,12 +1,11 @@ - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.OData.FunctionalTests Microsoft.EntityFrameworkCore - true True - + diff --git a/test/EFCore.Proxies.Tests/EFCore.Proxies.Tests.csproj b/test/EFCore.Proxies.Tests/EFCore.Proxies.Tests.csproj index 8b26bc1b1fe..c494ea7371d 100644 --- a/test/EFCore.Proxies.Tests/EFCore.Proxies.Tests.csproj +++ b/test/EFCore.Proxies.Tests/EFCore.Proxies.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Proxies.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Relational.Specification.Tests/EFCore.Relational.Specification.Tests.csproj b/test/EFCore.Relational.Specification.Tests/EFCore.Relational.Specification.Tests.csproj index 891cc0fa866..4d3d35d18ca 100644 --- a/test/EFCore.Relational.Specification.Tests/EFCore.Relational.Specification.Tests.csproj +++ b/test/EFCore.Relational.Specification.Tests/EFCore.Relational.Specification.Tests.csproj @@ -2,7 +2,7 @@ Shared test suite for Entity Framework Core relational database providers. - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Relational.Specification.Tests Microsoft.EntityFrameworkCore true diff --git a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeNoTrackingQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeNoTrackingQueryTestBase.cs index 8485ea7484f..3bc2d306412 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeNoTrackingQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeNoTrackingQueryTestBase.cs @@ -154,7 +154,7 @@ protected override Expression RewriteServerQueryExpression(Expression serverQuer serverQueryExpression = base.RewriteServerQueryExpression(serverQueryExpression); return Expression.Call( - _asSplitIncludeMethodInfo.MakeGenericMethod(serverQueryExpression.Type.TryGetSequenceType()), + _asSplitIncludeMethodInfo.MakeGenericMethod(serverQueryExpression.Type.GetSequenceType()), serverQueryExpression); } } diff --git a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeQueryTestBase.cs index 1bf45c0b5cf..de18c77121a 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSplitIncludeQueryTestBase.cs @@ -142,7 +142,7 @@ protected override Expression RewriteServerQueryExpression(Expression serverQuer serverQueryExpression = base.RewriteServerQueryExpression(serverQueryExpression); return Expression.Call( - _asSplitIncludeMethodInfo.MakeGenericMethod(serverQueryExpression.Type.TryGetSequenceType()), + _asSplitIncludeMethodInfo.MakeGenericMethod(serverQueryExpression.Type.GetSequenceType()), serverQueryExpression); } } diff --git a/test/EFCore.Relational.Tests/EFCore.Relational.Tests.csproj b/test/EFCore.Relational.Tests/EFCore.Relational.Tests.csproj index d2ff362d6e3..a201c553974 100644 --- a/test/EFCore.Relational.Tests/EFCore.Relational.Tests.csproj +++ b/test/EFCore.Relational.Tests/EFCore.Relational.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Relational.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Specification.Tests/EFCore.Specification.Tests.csproj b/test/EFCore.Specification.Tests/EFCore.Specification.Tests.csproj index 610e4f0533c..665c595cd29 100644 --- a/test/EFCore.Specification.Tests/EFCore.Specification.Tests.csproj +++ b/test/EFCore.Specification.Tests/EFCore.Specification.Tests.csproj @@ -2,7 +2,7 @@ Shared test suite for Entity Framework Core database providers. - $(StandardTestTfms) + net5.0 9.0 Microsoft.EntityFrameworkCore.Specification.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs b/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs index cc4f9643b94..f947893268a 100644 --- a/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs +++ b/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs @@ -2104,7 +2104,6 @@ public virtual void Can_serialize_proxies_to_JSON() Assert.IsType(blog); } -#if NET5_0 var options = new System.Text.Json.JsonSerializerOptions { ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve, WriteIndented = true }; serialized = System.Text.Json.JsonSerializer.Serialize(blogs, options); @@ -2177,7 +2176,6 @@ public virtual void Can_serialize_proxies_to_JSON() Assert.IsType(blog); } VerifyBlogs(newBlogs); -#endif } [ConditionalFact] diff --git a/test/EFCore.Specification.Tests/SerializationTestBase.cs b/test/EFCore.Specification.Tests/SerializationTestBase.cs index d9e99608e3c..97c38729dfd 100644 --- a/test/EFCore.Specification.Tests/SerializationTestBase.cs +++ b/test/EFCore.Specification.Tests/SerializationTestBase.cs @@ -122,7 +122,6 @@ private static T RoundtripThroughBclJson(T collection, bool ignoreLoops, bool { Assert.False(ignoreLoops, "BCL doesn't support ignoring loops."); -#if NET5_0 var options = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.Preserve, @@ -131,9 +130,6 @@ private static T RoundtripThroughBclJson(T collection, bool ignoreLoops, bool }; return JsonSerializer.Deserialize(JsonSerializer.Serialize(collection, options), options); -#else - return collection; -#endif } private static T RoundtripThroughNewtonsoftJson(T collection, bool ignoreLoops, bool writeIndented) diff --git a/test/EFCore.Specification.Tests/WithConstructorsTestBase.cs b/test/EFCore.Specification.Tests/WithConstructorsTestBase.cs index 4b4120b58a8..bd9a7ce0ed2 100644 --- a/test/EFCore.Specification.Tests/WithConstructorsTestBase.cs +++ b/test/EFCore.Specification.Tests/WithConstructorsTestBase.cs @@ -743,7 +743,6 @@ public virtual void Query_with_loader_delegate_injected_into_property_via_constr Assert.Same(blog, blog.LazyPcsPosts.Skip(1).First().LazyPcsBlog); } -#if NET5_0 [ConditionalFact] public virtual async Task Add_immutable_record() { @@ -765,7 +764,6 @@ public virtual async Task Add_immutable_record() Assert.Equal(title, context.Set().Single(e => e.BlogId == blogId).Title); } } -#endif protected class Blog { @@ -1581,7 +1579,6 @@ public async Task LoadBlogAsync(CancellationToken cancellationTok public LazyAsyncBlog LazyAsyncBlog { get; set; } } -#if NET5_0 protected record BlogAsImmutableRecord { public BlogAsImmutableRecord( @@ -1606,7 +1603,6 @@ private BlogAsImmutableRecord( public string Title { get; init; } public int? MonthlyRevenue { get; init; } } -#endif public class OtherContext : DbContext { @@ -1679,9 +1675,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity(); modelBuilder.Entity(); -#if NET5_0 modelBuilder.Entity(); -#endif // Manually configure service fields since there is no public API yet diff --git a/test/EFCore.SqlServer.FunctionalTests/EFCore.SqlServer.FunctionalTests.csproj b/test/EFCore.SqlServer.FunctionalTests/EFCore.SqlServer.FunctionalTests.csproj index f8333ed07d5..8cd8c7d42ea 100644 --- a/test/EFCore.SqlServer.FunctionalTests/EFCore.SqlServer.FunctionalTests.csproj +++ b/test/EFCore.SqlServer.FunctionalTests/EFCore.SqlServer.FunctionalTests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests Microsoft.EntityFrameworkCore True diff --git a/test/EFCore.SqlServer.Tests/EFCore.SqlServer.Tests.csproj b/test/EFCore.SqlServer.Tests/EFCore.SqlServer.Tests.csproj index 6fe3547b9aa..746ec1c4d38 100644 --- a/test/EFCore.SqlServer.Tests/EFCore.SqlServer.Tests.csproj +++ b/test/EFCore.SqlServer.Tests/EFCore.SqlServer.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.SqlServer.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj b/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj index c58af715a5e..c9fe4d12d0c 100644 --- a/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj +++ b/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Sqlite.FunctionalTests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Sqlite.Tests/EFCore.Sqlite.Tests.csproj b/test/EFCore.Sqlite.Tests/EFCore.Sqlite.Tests.csproj index 1d91e297752..fcdb5a6ff62 100644 --- a/test/EFCore.Sqlite.Tests/EFCore.Sqlite.Tests.csproj +++ b/test/EFCore.Sqlite.Tests/EFCore.Sqlite.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Sqlite.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Tests/EFCore.Tests.csproj b/test/EFCore.Tests/EFCore.Tests.csproj index 97e2a70fb7a..941f580d001 100644 --- a/test/EFCore.Tests/EFCore.Tests.csproj +++ b/test/EFCore.Tests/EFCore.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Tests Microsoft.EntityFrameworkCore diff --git a/test/EFCore.Tests/Storage/PhysicalAddressToBytesConverterTest.cs b/test/EFCore.Tests/Storage/PhysicalAddressToBytesConverterTest.cs index 8aa11bd4464..047d3ea6a0a 100644 --- a/test/EFCore.Tests/Storage/PhysicalAddressToBytesConverterTest.cs +++ b/test/EFCore.Tests/Storage/PhysicalAddressToBytesConverterTest.cs @@ -56,11 +56,9 @@ public static IEnumerable Data new object[] { "1D-4E-55-D6-92-73-D6" }, new object[] { "24-80-B7-38-4A-68-D6" }, new object[] { "1B-AB-DF-C7-3D-6B" }, -#if NET5_0 new object[] { "1D:4E:55:D6:92:73" }, new object[] { "24:80:B7:38:4A:68" }, new object[] { "1B:AB:DF:C7:3D:6B" }, -#endif new object[] { "1D4E55D69273" }, new object[] { "1BABDFC73D6B" }, new object[] { "0459D099E185" }, diff --git a/test/EFCore.Tests/Storage/PhysicalAddressToStringConverterTest.cs b/test/EFCore.Tests/Storage/PhysicalAddressToStringConverterTest.cs index b8f051c77b0..82abf38f98b 100644 --- a/test/EFCore.Tests/Storage/PhysicalAddressToStringConverterTest.cs +++ b/test/EFCore.Tests/Storage/PhysicalAddressToStringConverterTest.cs @@ -70,11 +70,9 @@ public static IEnumerable Data new object[] { "1D-4E-55-D6-92-73-D6" }, new object[] { "24-80-B7-38-4A-68-D6" }, new object[] { "04-59-D0-99-E1-85" }, -#if NET5_0 new object[] { "1D:4E:55:D6:92:73" }, new object[] { "24:80:B7:38:4A:68" }, new object[] { "04:59:D0:99:E1:85" }, -#endif new object[] { "1D4E55D69273" }, new object[] { "2480B7384A68" }, new object[] { "0459D099E185" }, diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj index a515f6863ea..45a5310a61a 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj @@ -1,7 +1,7 @@ - $(StandardTestTfms) + net5.0 $(DefineConstants);E_SQLITE3 diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj index eb2f6086a3f..93e6f74661f 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj @@ -1,7 +1,7 @@ - $(StandardTestTfms) + net5.0 $(DefineConstants);E_SQLCIPHER diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj index 13e3baf36f0..23876c27817 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj @@ -1,7 +1,7 @@ - $(StandardTestTfms) + net5.0 $(DefineConstants);SQLITE3 diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj index d737a5df060..6e7753dc77e 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj @@ -1,7 +1,7 @@ - $(StandardTestTfms) + net5.0 $(DefineConstants);WINSQLITE3 diff --git a/test/dotnet-ef.Tests/dotnet-ef.Tests.csproj b/test/dotnet-ef.Tests/dotnet-ef.Tests.csproj index 9a9b0aeaa1d..643afbd08b7 100644 --- a/test/dotnet-ef.Tests/dotnet-ef.Tests.csproj +++ b/test/dotnet-ef.Tests/dotnet-ef.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Tools diff --git a/test/ef.Tests/ef.Tests.csproj b/test/ef.Tests/ef.Tests.csproj index 85631f36ce4..80f4f5a91b2 100644 --- a/test/ef.Tests/ef.Tests.csproj +++ b/test/ef.Tests/ef.Tests.csproj @@ -1,7 +1,7 @@  - $(StandardTestTfms) + net5.0 Microsoft.EntityFrameworkCore.Tools