From aa9fa7b2cecfdb56f2e0bff18afabb96b6233d55 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 23 Jul 2019 13:05:02 -0700 Subject: [PATCH] More API review changes * Remove indexMap parameter of `IEntityMaterializerSource.CreateMaterializeExpression()` * Move `IsEFPropertyMethod` to `MethodInfoExtensions` * Rename `MemberIdentity` file * Made members private on `ExpressionPrinter` * Use `IReadOnlyList` instead of `IList` where appropriate * Added factory methods to `SqlFunctionExpression` * Seal `public override ExpressionType NodeType => ExpressionType.Extension;` * Added dependency object for QueryCompilationContext Part of #15662 --- .../Query/Internal/ContainsTranslator.cs | 2 +- .../CosmosMethodCallTranslatorProvider.cs | 2 +- .../Internal/EntityProjectionExpression.cs | 2 +- .../Query/Internal/EqualsTranslator.cs | 2 +- .../Query/Internal/IMethodCallTranslator.cs | 2 +- .../Internal/IMethodCallTranslatorProvider.cs | 2 +- .../ObjectArrayProjectionExpression.cs | 2 +- .../Query/Internal/OrderingExpression.cs | 2 +- .../Query/Internal/ProjectionExpression.cs | 2 +- .../Query/Internal/RootReferenceExpression.cs | 2 +- .../Query/Internal/SelectExpression.cs | 2 +- .../Query/Internal/SqlExpression.cs | 2 +- .../Query/Internal/EntityValuesExpression.cs | 2 +- .../Query/Internal/InMemoryQueryExpression.cs | 2 +- .../Query/Internal/InMemoryTableExpression.cs | 2 +- .../Query/CollectionInitializingExpression.cs | 2 +- .../Query/CollectionPopulatingExpression.cs | 2 +- .../Query/EntityProjectionExpression.cs | 2 +- .../Query/IMethodCallTranslator.cs | 2 +- .../Query/IMethodCallTranslatorProvider.cs | 2 +- .../Query/Internal/ComparisonTranslator.cs | 2 +- .../Query/Internal/ContainsTranslator.cs | 2 +- .../Query/Internal/EnumHasFlagTranslator.cs | 2 +- .../Query/Internal/EqualsTranslator.cs | 2 +- .../Internal/GetValueOrDefaultTranslator.cs | 2 +- .../Query/Internal/IsNullOrEmptyTranslator.cs | 2 +- .../Query/Internal/LikeTranslator.cs | 2 +- .../RelationalCollectionShaperExpression.cs | 2 +- .../RelationalMethodCallTranslatorProvider.cs | 2 +- ...yableMethodTranslatingExpressionVisitor.cs | 4 +- .../Query/SqlExpressionFactory.cs | 12 +- .../SqlExpressions/OrderingExpression.cs | 2 +- .../SqlExpressions/ProjectionExpression.cs | 2 +- .../Query/SqlExpressions/SelectExpression.cs | 2 - .../Query/SqlExpressions/SqlExpression.cs | 2 +- .../SqlExpressions/SqlFunctionExpression.cs | 29 +- .../SqlExpressions/TableExpressionBase.cs | 2 +- ...erverGeometryCollectionMethodTranslator.cs | 2 +- .../SqlServerGeometryMethodTranslator.cs | 2 +- .../SqlServerLineStringMethodTranslator.cs | 2 +- .../SqlServerPolygonMethodTranslator.cs | 2 +- .../Internal/SqlServerConvertTranslator.cs | 2 +- .../SqlServerDateDiffFunctionsTranslator.cs | 2 +- .../SqlServerDateTimeMethodTranslator.cs | 2 +- ...ServerFullTextSearchFunctionsTranslator.cs | 2 +- .../SqlServerIsDateFunctionTranslator.cs | 2 +- .../Query/Internal/SqlServerMathTranslator.cs | 2 +- .../Internal/SqlServerNewGuidTranslator.cs | 2 +- .../SqlServerObjectToStringTranslator.cs | 2 +- .../Internal/SqlServerQuerySqlGenerator.cs | 2 +- .../SqlServerStringMethodTranslator.cs | 2 +- .../Internal/SqliteDateTimeAddTranslator.cs | 2 +- .../Query/Internal/SqliteMathTranslator.cs | 2 +- .../Internal/SqliteStringMethodTranslator.cs | 4 +- ...qliteGeometryCollectionMethodTranslator.cs | 2 +- .../SqliteGeometryMethodTranslator.cs | 2 +- .../SqliteLineStringMethodTranslator.cs | 2 +- .../Internal/SqlitePolygonMethodTranslator.cs | 2 +- .../EntityFrameworkServicesBuilder.cs | 1 + .../Infrastructure/ExpressionExtensions.cs | 12 +- .../Infrastructure/MethodInfoExtensions.cs | 35 +++ ...{PropertyIdentity.cs => MemberIdentity.cs} | 0 src/EFCore/Metadata/ParameterBindingInfo.cs | 10 +- .../Query/CollectionShaperExpression.cs | 2 +- src/EFCore/Query/EntityMaterializerSource.cs | 8 +- src/EFCore/Query/EntityShaperExpression.cs | 2 +- src/EFCore/Query/ExpressionPrinter.cs | 8 +- src/EFCore/Query/GroupByShaperExpression.cs | 2 +- src/EFCore/Query/IEntityMaterializerSource.cs | 4 +- src/EFCore/Query/IncludeExpression.cs | 2 +- ...ntityEqualityRewritingExpressionVisitor.cs | 2 +- .../Internal/ExpressionEqualityComparer.cs | 2 +- .../Query/Internal/NullSafeEqualExpression.cs | 2 +- .../QueryCompilationContextFactory.cs | 43 +-- ...terializeCollectionNavigationExpression.cs | 2 +- .../CorrelationPredicateExpression.cs | 2 +- .../Internal/CustomRootExpression.cs | 2 +- .../Internal/NavigationBindingExpression.cs | 2 +- .../Internal/NavigationExpansionExpression.cs | 2 +- .../NavigationExpansionRootExpression.cs | 2 +- src/EFCore/Query/NullConditionalExpression.cs | 4 +- .../Query/ProjectionBindingExpression.cs | 2 +- src/EFCore/Query/QueryCompilationContext.cs | 31 +-- .../QueryCompilationContextDependencies.cs | 257 ++++++++++++++++++ src/EFCore/Query/ShapedQueryExpression.cs | 2 +- .../Query/UdfDbFunctionTestBase.cs | 8 +- .../Query/SpatialQuerySqlServerFixture.cs | 2 +- .../Query/SpatialQuerySqliteFixture.cs | 2 +- test/EFCore.Tests/ApiConsistencyTestBase.cs | 1 + ...QueryCompilationContextDependenciesTest.cs | 17 ++ 90 files changed, 438 insertions(+), 192 deletions(-) create mode 100644 src/EFCore/Infrastructure/MethodInfoExtensions.cs rename src/EFCore/Metadata/{PropertyIdentity.cs => MemberIdentity.cs} (100%) create mode 100644 src/EFCore/Query/QueryCompilationContextDependencies.cs create mode 100644 test/EFCore.Tests/Query/QueryCompilationContextDependenciesTest.cs diff --git a/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs b/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs index 2ca9b8fcc01..287bef77ea0 100644 --- a/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs @@ -40,7 +40,7 @@ public ContainsTranslator(ISqlExpressionFactory sqlExpressionFactory) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (method.IsGenericMethod && method.GetGenericMethodDefinition().Equals(_containsMethod)) diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs b/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs index 8d57bc4bb73..5f4dc4bd12b 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs @@ -49,7 +49,7 @@ public CosmosMethodCallTranslatorProvider( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { // TODO: UDF support. See issue#15338 //var dbFunction = model.FindDbFunction(method); diff --git a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs index d6db258d65a..d4262aa885a 100644 --- a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs @@ -43,7 +43,7 @@ public EntityProjectionExpression(IEntityType entityType, Expression accessExpre /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs b/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs index 6482081e96b..e0792a15f9e 100644 --- a/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs @@ -35,7 +35,7 @@ public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { SqlExpression left = null; SqlExpression right = null; diff --git a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs index 7db9a7a78c0..52b3d82700f 100644 --- a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslator.cs @@ -20,6 +20,6 @@ public interface IMethodCallTranslator /// 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. /// - SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments); + SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments); } } diff --git a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs index 4b3ee9d9424..588dcd2a7b1 100644 --- a/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs +++ b/src/EFCore.Cosmos/Query/Internal/IMethodCallTranslatorProvider.cs @@ -21,6 +21,6 @@ public interface IMethodCallTranslatorProvider /// 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. /// - SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IList arguments); + SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments); } } diff --git a/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs index 1fca00fc72f..5d6fdf83841 100644 --- a/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs @@ -49,7 +49,7 @@ public ObjectArrayProjectionExpression( /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs b/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs index 23493b261ca..6663b28993b 100644 --- a/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs @@ -49,7 +49,7 @@ public OrderingExpression(SqlExpression expression, bool ascending) /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs index a5842c345be..f3499ffdd5e 100644 --- a/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs @@ -66,7 +66,7 @@ public virtual string Name /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs b/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs index 30009b2d653..cf1f1f36d10 100644 --- a/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/RootReferenceExpression.cs @@ -33,7 +33,7 @@ public RootReferenceExpression(IEntityType entityType, string alias) /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs b/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs index 083669eef27..d3e16638f82 100644 --- a/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs @@ -365,7 +365,7 @@ public virtual void ReverseOrderings() /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs index cf1dde8862b..e6ee5cb86e2 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs @@ -59,7 +59,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.InMemory/Query/Internal/EntityValuesExpression.cs b/src/EFCore.InMemory/Query/Internal/EntityValuesExpression.cs index 8c74cbfc78d..e82b8bff9ed 100644 --- a/src/EFCore.InMemory/Query/Internal/EntityValuesExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/EntityValuesExpression.cs @@ -21,7 +21,7 @@ public EntityProjectionExpression( public virtual IEntityType EntityType { get; } public override Type Type => EntityType.ClrType; - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public virtual Expression BindProperty(IProperty property) { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index 2394530b8b9..47e720d7e22 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -283,7 +283,7 @@ public virtual void ApplyServerProjection() public virtual Expression ServerQueryExpression { get; set; } public virtual ParameterExpression ValueBufferParameter { get; } public override Type Type => typeof(IEnumerable); - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; private Expression CreateReadValueExpression( Type type, diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs index 02eb09b98b4..07f37fb029c 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs @@ -20,7 +20,7 @@ public InMemoryTableExpression(IEntityType entityType) public virtual IEntityType EntityType { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; protected override Expression VisitChildren(ExpressionVisitor visitor) { diff --git a/src/EFCore.Relational/Query/CollectionInitializingExpression.cs b/src/EFCore.Relational/Query/CollectionInitializingExpression.cs index 6ff19948efe..ee43b0b8689 100644 --- a/src/EFCore.Relational/Query/CollectionInitializingExpression.cs +++ b/src/EFCore.Relational/Query/CollectionInitializingExpression.cs @@ -52,7 +52,7 @@ public virtual void Print(ExpressionPrinter expressionPrinter) public override Type Type { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public virtual int CollectionId { get; } public virtual Expression Parent { get; } diff --git a/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs b/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs index 7a3e7826c13..4ecdb4c8be0 100644 --- a/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs +++ b/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs @@ -36,7 +36,7 @@ public virtual void Print(ExpressionPrinter expressionPrinter) public override Type Type { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public virtual RelationalCollectionShaperExpression Parent { get; } public virtual bool IsInclude { get; } } diff --git a/src/EFCore.Relational/Query/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs index 4e9d6bc5186..fd2f49266de 100644 --- a/src/EFCore.Relational/Query/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -85,7 +85,7 @@ public virtual EntityProjectionExpression UpdateEntityType(IEntityType derivedTy } public virtual IEntityType EntityType { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => EntityType.ClrType; public virtual ColumnExpression BindProperty(IProperty property) diff --git a/src/EFCore.Relational/Query/IMethodCallTranslator.cs b/src/EFCore.Relational/Query/IMethodCallTranslator.cs index 1301fb46f8b..f3f5844b589 100644 --- a/src/EFCore.Relational/Query/IMethodCallTranslator.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslator.cs @@ -9,6 +9,6 @@ namespace Microsoft.EntityFrameworkCore.Query { public interface IMethodCallTranslator { - SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments); + SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments); } } diff --git a/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs index 96ad71a1f97..a6d84e27977 100644 --- a/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs @@ -10,6 +10,6 @@ namespace Microsoft.EntityFrameworkCore.Query { public interface IMethodCallTranslatorProvider { - SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IList arguments); + SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments); } } diff --git a/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs index c20e44eb49c..f87e937d463 100644 --- a/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs @@ -17,7 +17,7 @@ public ComparisonTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (method.ReturnType == typeof(int)) { diff --git a/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs index 9532de5de35..167923d8e00 100644 --- a/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs @@ -23,7 +23,7 @@ public ContainsTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (method.IsGenericMethod && method.GetGenericMethodDefinition().Equals(_containsMethod)) diff --git a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs index d76a8af23b6..4e5a1fa0e17 100644 --- a/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs @@ -20,7 +20,7 @@ public EnumHasFlagTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _methodInfo)) { diff --git a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs index 130a4753d13..dfc56b637f2 100644 --- a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs @@ -18,7 +18,7 @@ public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { SqlExpression left = null; SqlExpression right = null; diff --git a/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs index 1b5b094061b..11136e82ec7 100644 --- a/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs @@ -17,7 +17,7 @@ public GetValueOrDefaultTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (method.Name == nameof(Nullable.GetValueOrDefault) && method.ReturnType.IsNumeric()) diff --git a/src/EFCore.Relational/Query/Internal/IsNullOrEmptyTranslator.cs b/src/EFCore.Relational/Query/Internal/IsNullOrEmptyTranslator.cs index f9d60b1bf81..fc41626e998 100644 --- a/src/EFCore.Relational/Query/Internal/IsNullOrEmptyTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/IsNullOrEmptyTranslator.cs @@ -22,7 +22,7 @@ public StringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _isNullOrEmptyMethodInfo)) { diff --git a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs index 5fa8a4f9c35..456ace2a9e3 100644 --- a/src/EFCore.Relational/Query/Internal/LikeTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs @@ -26,7 +26,7 @@ public LikeTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _methodInfo)) { diff --git a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs index 2617d1f4787..d72e3446713 100644 --- a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs @@ -37,7 +37,7 @@ public RelationalCollectionShaperExpression( public virtual Type ElementType { get; } public override Type Type => Navigation?.ClrType ?? typeof(List<>).MakeGenericType(ElementType); - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; protected override Expression VisitChildren(ExpressionVisitor visitor) { diff --git a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs index 17e51ca5da0..f2114375457 100644 --- a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs @@ -36,7 +36,7 @@ public RelationalMethodCallTranslatorProvider([NotNull] RelationalMethodCallTran _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { var dbFunction = model.FindDbFunction(method); if (dbFunction != null) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 6eecbe45866..40e3d5fd0f0 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -503,8 +503,8 @@ private SqlBinaryExpression CreateJoinPredicate( } private SqlBinaryExpression CreateJoinPredicate( - IList outerExpressions, - IList innerExpressions) + IReadOnlyList outerExpressions, + IReadOnlyList innerExpressions) { SqlBinaryExpression result = null; for (var i = 0; i < outerExpressions.Count; i++) diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index a4526f3c083..cabab58bee2 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -319,7 +319,7 @@ public virtual SqlFunctionExpression Function( typeMappedArguments.Add(ApplyDefaultTypeMapping(argument)); } - return new SqlFunctionExpression( + return SqlFunctionExpression.Create( name, typeMappedArguments, returnType, @@ -335,7 +335,7 @@ public virtual SqlFunctionExpression Function( typeMappedArguments.Add(ApplyDefaultTypeMapping(argument)); } - return new SqlFunctionExpression( + return SqlFunctionExpression.Create( schema, name, typeMappedArguments, @@ -353,7 +353,7 @@ public virtual SqlFunctionExpression Function( typeMappedArguments.Add(ApplyDefaultTypeMapping(argument)); } - return new SqlFunctionExpression( + return SqlFunctionExpression.Create( instance, name, typeMappedArguments, @@ -362,13 +362,13 @@ public virtual SqlFunctionExpression Function( } public virtual SqlFunctionExpression Function(string name, Type returnType, RelationalTypeMapping typeMapping = null) - => new SqlFunctionExpression(name, returnType, typeMapping); + => SqlFunctionExpression.CreateNiladic(name, returnType, typeMapping); public virtual SqlFunctionExpression Function(string schema, string name, Type returnType, RelationalTypeMapping typeMapping = null) - => new SqlFunctionExpression(schema, name, returnType, typeMapping); + => SqlFunctionExpression.CreateNiladic(schema, name, returnType, typeMapping); public virtual SqlFunctionExpression Function(SqlExpression instance, string name, Type returnType, RelationalTypeMapping typeMapping = null) - => new SqlFunctionExpression(ApplyDefaultTypeMapping(instance), name, returnType, typeMapping); + => SqlFunctionExpression.CreateNiladic(ApplyDefaultTypeMapping(instance), name, returnType, typeMapping); public virtual ExistsExpression Exists(SelectExpression subquery, bool negated) => new ExistsExpression(subquery, negated, _boolTypeMapping); diff --git a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs index e2869be33f1..1376e871a0e 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs @@ -17,7 +17,7 @@ public OrderingExpression(SqlExpression expression, bool ascending) public virtual SqlExpression Expression { get; } public virtual bool IsAscending { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => Expression.Type; protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression)); diff --git a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs index 85a698774eb..1d211b297b6 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs @@ -18,7 +18,7 @@ public ProjectionExpression(SqlExpression expression, string alias) public virtual SqlExpression Expression { get; } public override Type Type => Expression.Type; - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression)); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index ac4929d33f8..4904b926f8c 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -261,8 +261,6 @@ public void ApplyPredicate(SqlExpression expression) } } - public override ExpressionType NodeType => ExpressionType.Extension; - public Expression ApplyGrouping(Expression keySelector) { ClearOrdering(); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs index cdf1e4749d3..7e3df868858 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs @@ -21,7 +21,7 @@ protected SqlExpression(Type type, RelationalTypeMapping typeMapping) protected override Expression VisitChildren(ExpressionVisitor visitor) => throw new InvalidOperationException("VisitChildren must be overridden in class deriving from SqlExpression"); - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public abstract void Print(ExpressionPrinter expressionPrinter); public override bool Equals(object obj) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs index 3208462fefc..52e7cba503f 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs @@ -11,65 +11,62 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlFunctionExpression : SqlExpression { - // niladic - public SqlFunctionExpression( + public static SqlFunctionExpression CreateNiladic( string name, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping) { + return new SqlFunctionExpression(instance: null, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); } - // niladic - public SqlFunctionExpression( + public static SqlFunctionExpression CreateNiladic( string schema, string name, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema, name, niladic: true, arguments: null, builtIn: true, type, typeMapping) { + return new SqlFunctionExpression(instance: null, schema, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); } - // niladic - public SqlFunctionExpression( + public static SqlFunctionExpression CreateNiladic( SqlExpression instance, string name, Type type, RelationalTypeMapping typeMapping) - : this(instance, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping) { + return new SqlFunctionExpression(instance, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping); } - public SqlFunctionExpression( + public static SqlFunctionExpression Create( SqlExpression instance, string name, IEnumerable arguments, Type type, RelationalTypeMapping typeMapping) - : this(instance, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping) { + return new SqlFunctionExpression(instance, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping); } - public SqlFunctionExpression( + public static SqlFunctionExpression Create( string name, IEnumerable arguments, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping) { + return new SqlFunctionExpression(instance: null, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping); } - public SqlFunctionExpression( + public static SqlFunctionExpression Create( string schema, string name, IEnumerable arguments, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema, name, niladic: false, arguments, builtIn: false, type, typeMapping) { + return new SqlFunctionExpression(instance: null, schema, name, niladic: false, arguments, builtIn: false, type, typeMapping); } - private SqlFunctionExpression( + public SqlFunctionExpression( Expression instance, string schema, string name, diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs index cc31cf74d1f..74419f131d6 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs @@ -22,7 +22,7 @@ protected TableExpressionBase([CanBeNull] string alias) protected override Expression VisitChildren(ExpressionVisitor visitor) => this; public override Type Type => typeof(object); - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public abstract void Print(ExpressionPrinter expressionPrinter); public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs index 0e78b5d47f2..a7fb18f7735 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs @@ -24,7 +24,7 @@ public SqlServerGeometryCollectionMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _item)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs index 7aa99ecc37e..133ccad2a36 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs @@ -57,7 +57,7 @@ public SqlServerGeometryMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (typeof(Geometry).IsAssignableFrom(method.DeclaringType)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs index eaa8f1bf7b5..882cb94e429 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs @@ -25,7 +25,7 @@ public SqlServerLineStringMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _getPointN)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs index 02335f66b92..3d556a14895 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs @@ -26,7 +26,7 @@ public SqlServerPolygonMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _getInteriorRingN)) { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs index ae80197094f..ee9406293c3 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs @@ -50,7 +50,7 @@ public SqlServerConvertTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { return _supportedMethods.Contains(method) ? _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs index c385e075a3d..414aeca53e6 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs @@ -311,7 +311,7 @@ public SqlServerDateDiffFunctionsTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_methodInfoDateDiffMapping.TryGetValue(method, out var datePart)) { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs index ac912eb4517..ed509ca6b18 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs @@ -36,7 +36,7 @@ public SqlServerDateTimeMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_methodInfoDatePartMapping.TryGetValue(method, out var datePart)) { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs index d523978ba09..7ac60f01793 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs @@ -51,7 +51,7 @@ public SqlServerFullTextSearchFunctionsTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_functionMapping.TryGetValue(method, out var functionName)) { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs index c838f3ec8d7..eca1b1b090f 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs @@ -18,7 +18,7 @@ public class SqlServerIsDateFunctionTranslator : IMethodCallTranslator public SqlServerIsDateFunctionTranslator(ISqlExpressionFactory sqlExpressionFactory) => _sqlExpressionFactory = sqlExpressionFactory; - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { return _methodInfo.Equals(method) ? _sqlExpressionFactory.Convert( diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs index e14779ffca0..038ab5e0bda 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs @@ -67,7 +67,7 @@ public SqlServerMathTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_supportedMethodTranslations.TryGetValue(method, out var sqlFunctionName)) { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs index 2b6c7d648e1..bc08eb8a415 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs @@ -19,7 +19,7 @@ public SqlServerNewGuidTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { return _methodInfo.Equals(method) ? _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs index 7a8cfeba23b..4c109c2946b 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs @@ -41,7 +41,7 @@ public SqlServerObjectToStringTranslator(ISqlExpressionFactory sqlExpressionFact _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { return method.Name == nameof(ToString) && arguments.Count == 0 diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs index 1742cb823e1..89ca2cb8759 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs @@ -58,7 +58,7 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction if (!sqlFunctionExpression.IsBuiltIn && string.IsNullOrEmpty(sqlFunctionExpression.Schema)) { - sqlFunctionExpression = new SqlFunctionExpression( + sqlFunctionExpression = SqlFunctionExpression.Create( schema: "dbo", sqlFunctionExpression.Name, sqlFunctionExpression.Arguments, diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index 016bc83e8e3..4ebf5b408f2 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -57,7 +57,7 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_indexOfMethodInfo.Equals(method)) { diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs index ba51ac68053..b0cd3240a1f 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs @@ -33,7 +33,7 @@ public SqliteDateTimeAddTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { SqlExpression modifier = null; if (_addMilliseconds.Equals(method)) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs index c92e5a98ebb..c8469592a41 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs @@ -49,7 +49,7 @@ public SqliteMathTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_supportedMethods.TryGetValue(method, out var sqlFunctionName)) { diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs index 5593a60a708..9b5464cfae6 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs @@ -64,7 +64,7 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_indexOfMethodInfo.Equals(method)) { @@ -287,7 +287,7 @@ private string EscapeLikePattern(string pattern) return builder.ToString(); } - private SqlExpression ProcessTrimMethod(SqlExpression instance, IList arguments, string functionName) + private SqlExpression ProcessTrimMethod(SqlExpression instance, IReadOnlyList arguments, string functionName) { var typeMapping = instance.TypeMapping; if (typeMapping == null) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs index 0bf492f0590..73f6cb7e8ee 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs @@ -19,7 +19,7 @@ public SqliteGeometryCollectionMethodTranslator(ISqlExpressionFactory sqlExpress _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _item)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs index c442876f6b4..2feb510e523 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs @@ -52,7 +52,7 @@ public SqliteGeometryMethodTranslator(ISqlExpressionFactory sqlExpressionFactory _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (_methodToFunctionName.TryGetValue(method, out var functionName)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs index 3154ea9d6f5..c9ab74e0e7f 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs @@ -20,7 +20,7 @@ public SqliteLineStringMethodTranslator(ISqlExpressionFactory sqlExpressionFacto _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _getPointN)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs index 49012d6ff5b..dc6b974f04b 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs @@ -21,7 +21,7 @@ public SqlitePolygonMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments) { if (Equals(method, _getInteriorRingN)) { diff --git a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs index eedca6b9915..321cfdb6e58 100644 --- a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs +++ b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs @@ -282,6 +282,7 @@ public virtual EntityFrameworkServicesBuilder TryAddCoreServices() .AddDependencySingleton() .AddDependencySingleton() .AddDependencyScoped() + .AddDependencyScoped() .AddDependencyScoped() .AddDependencyScoped() .AddDependencyScoped() diff --git a/src/EFCore/Infrastructure/ExpressionExtensions.cs b/src/EFCore/Infrastructure/ExpressionExtensions.cs index b23404cf3a9..459db742ee0 100644 --- a/src/EFCore/Infrastructure/ExpressionExtensions.cs +++ b/src/EFCore/Infrastructure/ExpressionExtensions.cs @@ -25,18 +25,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// public static class ExpressionExtensions { - private static readonly string _efTypeName = typeof(EF).FullName; - - public static bool IsEFPropertyMethod([CanBeNull] this MethodInfo methodInfo) - => Equals(methodInfo, EF.PropertyMethod) - // fallback to string comparison because MethodInfo.Equals is not - // always true in .NET Native even if methods are the same - || methodInfo?.IsGenericMethod == true - && methodInfo.Name == nameof(EF.Property) - && methodInfo.DeclaringType?.FullName == _efTypeName; - public static bool IsEFProperty([NotNull] this MethodCallExpression methodCallExpression) - => IsEFPropertyMethod(methodCallExpression.Method); + => methodCallExpression.Method.IsEFPropertyMethod(); public static bool TryGetEFPropertyArguments( [NotNull] this MethodCallExpression methodCallExpression, diff --git a/src/EFCore/Infrastructure/MethodInfoExtensions.cs b/src/EFCore/Infrastructure/MethodInfoExtensions.cs new file mode 100644 index 00000000000..04423e4b8aa --- /dev/null +++ b/src/EFCore/Infrastructure/MethodInfoExtensions.cs @@ -0,0 +1,35 @@ +// 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.Reflection; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Infrastructure +{ + /// + /// + /// Extension methods for . + /// + /// + /// This type is typically used by database providers (and other extensions). It is generally + /// not used in application code. + /// + /// + public static class MethodInfoExtensions + { + private static readonly string _efTypeName = typeof(EF).FullName; + + /// + /// Returns true if the given method is . + /// + /// The method. + /// True if the method is ; false otherwise. + public static bool IsEFPropertyMethod([CanBeNull] this MethodInfo methodInfo) + => Equals(methodInfo, EF.PropertyMethod) + // fallback to string comparison because MethodInfo.Equals is not + // always true in .NET Native even if methods are the same + || methodInfo?.IsGenericMethod == true + && methodInfo.Name == nameof(EF.Property) + && methodInfo.DeclaringType?.FullName == _efTypeName; + } +} diff --git a/src/EFCore/Metadata/PropertyIdentity.cs b/src/EFCore/Metadata/MemberIdentity.cs similarity index 100% rename from src/EFCore/Metadata/PropertyIdentity.cs rename to src/EFCore/Metadata/MemberIdentity.cs diff --git a/src/EFCore/Metadata/ParameterBindingInfo.cs b/src/EFCore/Metadata/ParameterBindingInfo.cs index b8ad09e0905..acd0d53f5b0 100644 --- a/src/EFCore/Metadata/ParameterBindingInfo.cs +++ b/src/EFCore/Metadata/ParameterBindingInfo.cs @@ -14,23 +14,18 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// public readonly struct ParameterBindingInfo { - private readonly int[] _indexMap; - /// /// Creates a new to define a parameter binding. /// /// The entity type for this binding. /// The expression tree from which the parameter value will come. - /// An optional index map for finding the parameter value. public ParameterBindingInfo( [NotNull] IEntityType entityType, - [NotNull] Expression materializationContextExpression, - [CanBeNull] int[] indexMap) + [NotNull] Expression materializationContextExpression) { Check.NotNull(entityType, nameof(entityType)); Check.NotNull(materializationContextExpression, nameof(materializationContextExpression)); - _indexMap = indexMap; EntityType = entityType; MaterializationContextExpression = materializationContextExpression; } @@ -50,7 +45,6 @@ public ParameterBindingInfo( /// /// The property. /// The index where its value can be found. - public int GetValueBufferIndex([NotNull] IPropertyBase property) - => _indexMap?[property.GetIndex()] ?? property.GetIndex(); + public int GetValueBufferIndex([NotNull] IPropertyBase property) => property.GetIndex(); } } diff --git a/src/EFCore/Query/CollectionShaperExpression.cs b/src/EFCore/Query/CollectionShaperExpression.cs index 8dc82978528..59b2e4ac0ed 100644 --- a/src/EFCore/Query/CollectionShaperExpression.cs +++ b/src/EFCore/Query/CollectionShaperExpression.cs @@ -35,7 +35,7 @@ public virtual CollectionShaperExpression Update(Expression projection, Expressi ? new CollectionShaperExpression(projection, innerShaper, Navigation, ElementType) : this; - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => Navigation?.ClrType ?? typeof(List<>).MakeGenericType(ElementType); public virtual Expression Projection { get; } diff --git a/src/EFCore/Query/EntityMaterializerSource.cs b/src/EFCore/Query/EntityMaterializerSource.cs index e4cc2f5f10b..6adee58520d 100644 --- a/src/EFCore/Query/EntityMaterializerSource.cs +++ b/src/EFCore/Query/EntityMaterializerSource.cs @@ -57,8 +57,7 @@ private static TValue TryReadValue( public virtual Expression CreateMaterializeExpression( IEntityType entityType, string entityInstanceName, - Expression materializationContextExpression, - int[] indexMap = null) + Expression materializationContextExpression) { if (!entityType.HasClrType()) { @@ -86,8 +85,7 @@ public virtual Expression CreateMaterializeExpression( var bindingInfo = new ParameterBindingInfo( entityType, - materializationContextExpression, - indexMap); + materializationContextExpression); var properties = new HashSet( entityType.GetServiceProperties().Cast() @@ -132,7 +130,7 @@ var readValueExpression : CreateReadValueExpression( valueBufferExpression, memberInfo.GetMemberType(), - indexMap?[property.GetIndex()] ?? property.GetIndex(), + property.GetIndex(), property); blockExpressions.Add( diff --git a/src/EFCore/Query/EntityShaperExpression.cs b/src/EFCore/Query/EntityShaperExpression.cs index 048bd47ec55..ea6dd27d3ac 100644 --- a/src/EFCore/Query/EntityShaperExpression.cs +++ b/src/EFCore/Query/EntityShaperExpression.cs @@ -43,7 +43,7 @@ public virtual EntityShaperExpression Update(Expression valueBufferExpression) : this; public override Type Type => EntityType.ClrType; - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public virtual void Print(ExpressionPrinter expressionPrinter) { diff --git a/src/EFCore/Query/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs index 9bdf160da74..523f2b00351 100644 --- a/src/EFCore/Query/ExpressionPrinter.cs +++ b/src/EFCore/Query/ExpressionPrinter.cs @@ -51,11 +51,11 @@ public ExpressionPrinter() public virtual IndentedStringBuilder StringBuilder => _stringBuilder; - public virtual bool RemoveFormatting { get; set; } + private bool RemoveFormatting { get; set; } - public virtual int? CharacterLimit { get; set; } + private int? CharacterLimit { get; set; } - public virtual bool PrintConnections { get; set; } + private bool PrintConnections { get; set; } public virtual void VisitList( IReadOnlyList items, @@ -832,7 +832,7 @@ protected override Expression VisitExtension(Expression extensionExpression) return extensionExpression; } - private void VisitArguments(IList arguments, Action appendAction, string lastSeparator = "", bool areConnected = false) + private void VisitArguments(IReadOnlyList arguments, Action appendAction, string lastSeparator = "", bool areConnected = false) { for (var i = 0; i < arguments.Count; i++) { diff --git a/src/EFCore/Query/GroupByShaperExpression.cs b/src/EFCore/Query/GroupByShaperExpression.cs index 7995d525411..a1ce4b40ffb 100644 --- a/src/EFCore/Query/GroupByShaperExpression.cs +++ b/src/EFCore/Query/GroupByShaperExpression.cs @@ -19,7 +19,7 @@ public GroupByShaperExpression(Expression keySelector, Expression elementSelecto public virtual Expression ElementSelector { get; } public override Type Type => typeof(IGrouping<,>).MakeGenericType(KeySelector.Type, ElementSelector.Type); - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public virtual void Print(ExpressionPrinter expressionPrinter) { diff --git a/src/EFCore/Query/IEntityMaterializerSource.cs b/src/EFCore/Query/IEntityMaterializerSource.cs index eed719facd2..3a2a52eb4cd 100644 --- a/src/EFCore/Query/IEntityMaterializerSource.cs +++ b/src/EFCore/Query/IEntityMaterializerSource.cs @@ -59,13 +59,11 @@ Expression CreateReadValueExpression( /// The entity type being materialized. /// The name of the instance being materialized. /// The materialization expression to build on. - /// An optional index map for reading values. /// An expression to read the value. Expression CreateMaterializeExpression( [NotNull] IEntityType entityType, [NotNull] string entityInstanceName, - [NotNull] Expression materializationExpression, - [CanBeNull] int[] indexMap = null); + [NotNull] Expression materializationExpression); /// /// diff --git a/src/EFCore/Query/IncludeExpression.cs b/src/EFCore/Query/IncludeExpression.cs index c3a00c28de0..3c5e99b56db 100644 --- a/src/EFCore/Query/IncludeExpression.cs +++ b/src/EFCore/Query/IncludeExpression.cs @@ -21,7 +21,7 @@ public IncludeExpression(Expression entityExpression, Expression navigationExpre public virtual Expression NavigationExpression { get; set; } public virtual INavigation Navigation { get; set; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override bool CanReduce => false; public override Type Type { get; } diff --git a/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs index 1d7b6284eed..239a839237d 100644 --- a/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs @@ -788,7 +788,7 @@ protected static Expression Unwrap(Expression expression) protected class EntityReferenceExpression : Expression { - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// The underlying expression being wrapped. diff --git a/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs b/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs index fd3ec766bc0..81eac3c2b4a 100644 --- a/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs +++ b/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs @@ -305,7 +305,7 @@ public virtual int GetHashCode(Expression obj) } } - private void AddListToHash(ref HashCode hash, IList expressions) + private void AddListToHash(ref HashCode hash, IReadOnlyList expressions) where T : Expression { for (var i = 0; i < expressions.Count; i++) diff --git a/src/EFCore/Query/Internal/NullSafeEqualExpression.cs b/src/EFCore/Query/Internal/NullSafeEqualExpression.cs index e2f396220ae..d1772f954c4 100644 --- a/src/EFCore/Query/Internal/NullSafeEqualExpression.cs +++ b/src/EFCore/Query/Internal/NullSafeEqualExpression.cs @@ -71,7 +71,7 @@ public NullSafeEqualExpression( /// 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 ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs b/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs index 517ffe6d4d9..42ca0c57444 100644 --- a/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs +++ b/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs @@ -1,53 +1,18 @@ // 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 Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; - namespace Microsoft.EntityFrameworkCore.Query.Internal { public class QueryCompilationContextFactory : IQueryCompilationContextFactory { - private readonly IModel _model; - private readonly IQueryOptimizerFactory _queryOptimizerFactory; - private readonly IQueryableMethodTranslatingExpressionVisitorFactory _queryableMethodTranslatingExpressionVisitorFactory; - private readonly IShapedQueryOptimizerFactory _shapedQueryOptimizerFactory; - private readonly IShapedQueryCompilingExpressionVisitorFactory _shapedQueryCompilingExpressionVisitorFactory; - private readonly ICurrentDbContext _currentContext; - private readonly IDbContextOptions _contextOptions; - private readonly IDiagnosticsLogger _logger; + private readonly QueryCompilationContextDependencies _dependencies; - public QueryCompilationContextFactory( - IModel model, - IQueryOptimizerFactory queryOptimizerFactory, - IQueryableMethodTranslatingExpressionVisitorFactory queryableMethodTranslatingExpressionVisitorFactory, - IShapedQueryOptimizerFactory shapedQueryOptimizerFactory, - IShapedQueryCompilingExpressionVisitorFactory shapedQueryCompilingExpressionVisitorFactory, - ICurrentDbContext currentContext, - IDbContextOptions contextOptions, - IDiagnosticsLogger logger) + public QueryCompilationContextFactory(QueryCompilationContextDependencies dependencies) { - _model = model; - _queryOptimizerFactory = queryOptimizerFactory; - _queryableMethodTranslatingExpressionVisitorFactory = queryableMethodTranslatingExpressionVisitorFactory; - _shapedQueryOptimizerFactory = shapedQueryOptimizerFactory; - _shapedQueryCompilingExpressionVisitorFactory = shapedQueryCompilingExpressionVisitorFactory; - _currentContext = currentContext; - _contextOptions = contextOptions; - _logger = logger; + _dependencies = dependencies; } public virtual QueryCompilationContext Create(bool async) - => new QueryCompilationContext( - _model, - _queryOptimizerFactory, - _queryableMethodTranslatingExpressionVisitorFactory, - _shapedQueryOptimizerFactory, - _shapedQueryCompilingExpressionVisitorFactory, - _currentContext, - _contextOptions, - _logger, - async); + => new QueryCompilationContext(_dependencies, async); } } diff --git a/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs index daa423d1ded..f9ccca185fa 100644 --- a/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs +++ b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs @@ -18,7 +18,7 @@ public MaterializeCollectionNavigationExpression(Expression subquery, INavigatio public virtual Expression Subquery { get; } public virtual INavigation Navigation { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => Navigation.ClrType; protected override Expression VisitChildren(ExpressionVisitor visitor) diff --git a/src/EFCore/Query/NavigationExpansion/Internal/CorrelationPredicateExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/CorrelationPredicateExpression.cs index f93e9f205d7..fd8a568b515 100644 --- a/src/EFCore/Query/NavigationExpansion/Internal/CorrelationPredicateExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/CorrelationPredicateExpression.cs @@ -30,7 +30,7 @@ public CorrelationPredicateExpression( public override bool CanReduce => true; - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Expression Reduce() => AndAlso( diff --git a/src/EFCore/Query/NavigationExpansion/Internal/CustomRootExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/CustomRootExpression.cs index ab5bf2ecc31..c5dd7455e35 100644 --- a/src/EFCore/Query/NavigationExpansion/Internal/CustomRootExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/CustomRootExpression.cs @@ -12,7 +12,7 @@ public class CustomRootExpression : Expression, IPrintable { public virtual ParameterExpression RootParameter { get; } public virtual List Mapping { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override bool CanReduce => false; public override Type Type { get; } diff --git a/src/EFCore/Query/NavigationExpansion/Internal/NavigationBindingExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationBindingExpression.cs index c654878e37a..eb44a3c8c56 100644 --- a/src/EFCore/Query/NavigationExpansion/Internal/NavigationBindingExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationBindingExpression.cs @@ -30,7 +30,7 @@ public NavigationBindingExpression( public virtual NavigationTreeNode NavigationTreeNode { get; } public virtual SourceMapping SourceMapping { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override bool CanReduce => false; public override Type Type { get; } diff --git a/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpression.cs index 4a77cd5cd00..ab3c3b7e4e7 100644 --- a/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpression.cs @@ -27,7 +27,7 @@ public NavigationExpansionExpression( public virtual Expression Operand { get; } public virtual NavigationExpansionExpressionState State { get; private set; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => _returnType; public override bool CanReduce => false; diff --git a/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionRootExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionRootExpression.cs index 383eae7ab84..032946388d2 100644 --- a/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionRootExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionRootExpression.cs @@ -20,7 +20,7 @@ public NavigationExpansionRootExpression(NavigationExpansionExpression navigatio public virtual NavigationExpansionExpression NavigationExpansion { get; } public virtual List Mapping { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override bool CanReduce => false; public override Type Type => NavigationExpansion.Type; diff --git a/src/EFCore/Query/NullConditionalExpression.cs b/src/EFCore/Query/NullConditionalExpression.cs index 0e2317a1f68..5a190ea7905 100644 --- a/src/EFCore/Query/NullConditionalExpression.cs +++ b/src/EFCore/Query/NullConditionalExpression.cs @@ -63,7 +63,7 @@ public NullConditionalExpression( /// /// Gets the node type of this expression. /// - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; /// /// Reduces this node to a simpler expression. If CanReduce returns true, this should @@ -160,7 +160,7 @@ public virtual void Print(ExpressionPrinter expressionPrinter) expressionPrinter.StringBuilder.Append("?"); } - private static void VisitArguments(ExpressionPrinter expressionPrinter, IList arguments) + private static void VisitArguments(ExpressionPrinter expressionPrinter, IReadOnlyList arguments) { for (var i = 0; i < arguments.Count; i++) { diff --git a/src/EFCore/Query/ProjectionBindingExpression.cs b/src/EFCore/Query/ProjectionBindingExpression.cs index 00bbe1923ec..361ad7944d6 100644 --- a/src/EFCore/Query/ProjectionBindingExpression.cs +++ b/src/EFCore/Query/ProjectionBindingExpression.cs @@ -37,7 +37,7 @@ public ProjectionBindingExpression(Expression queryExpression, IDictionary IndexMap { get; } public override Type Type { get; } - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; protected override Expression VisitChildren(ExpressionVisitor visitor) => this; diff --git a/src/EFCore/Query/QueryCompilationContext.cs b/src/EFCore/Query/QueryCompilationContext.cs index 0de543bdaa2..f373ecbc23c 100644 --- a/src/EFCore/Query/QueryCompilationContext.cs +++ b/src/EFCore/Query/QueryCompilationContext.cs @@ -29,27 +29,22 @@ public class QueryCompilationContext private Dictionary _runtimeParameters; public QueryCompilationContext( - IModel model, - IQueryOptimizerFactory queryOptimizerFactory, - IQueryableMethodTranslatingExpressionVisitorFactory queryableMethodTranslatingExpressionVisitorFactory, - IShapedQueryOptimizerFactory shapedQueryOptimizerFactory, - IShapedQueryCompilingExpressionVisitorFactory shapedQueryCompilingExpressionVisitorFactory, - ICurrentDbContext currentContext, - IDbContextOptions contextOptions, - IDiagnosticsLogger logger, + QueryCompilationContextDependencies dependencies, bool async) { + var context = dependencies.CurrentContext.Context; + IsAsync = async; - IsTracking = currentContext.Context.ChangeTracker.QueryTrackingBehavior == QueryTrackingBehavior.TrackAll; - Model = model; - ContextOptions = contextOptions; - ContextType = currentContext.Context.GetType(); - Logger = logger; - - _queryOptimizerFactory = queryOptimizerFactory; - _queryableMethodTranslatingExpressionVisitorFactory = queryableMethodTranslatingExpressionVisitorFactory; - _shapedQueryOptimizerFactory = shapedQueryOptimizerFactory; - _shapedQueryCompilingExpressionVisitorFactory = shapedQueryCompilingExpressionVisitorFactory; + IsTracking = context.ChangeTracker.QueryTrackingBehavior == QueryTrackingBehavior.TrackAll; + Model = dependencies.Model; + ContextOptions = dependencies.ContextOptions; + ContextType = context.GetType(); + Logger = dependencies.Logger; + + _queryOptimizerFactory = dependencies.QueryOptimizerFactory; + _queryableMethodTranslatingExpressionVisitorFactory = dependencies.QueryableMethodTranslatingExpressionVisitorFactory; + _shapedQueryOptimizerFactory = dependencies.ShapedQueryOptimizerFactory; + _shapedQueryCompilingExpressionVisitorFactory = dependencies.ShapedQueryCompilingExpressionVisitorFactory; } public virtual bool IsAsync { get; } diff --git a/src/EFCore/Query/QueryCompilationContextDependencies.cs b/src/EFCore/Query/QueryCompilationContextDependencies.cs new file mode 100644 index 00000000000..971a2baf949 --- /dev/null +++ b/src/EFCore/Query/QueryCompilationContextDependencies.cs @@ -0,0 +1,257 @@ +// 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 JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.EntityFrameworkCore.Query +{ + /// + /// + /// Service dependencies parameter class for + /// + /// + /// This type is typically used by database providers (and other extensions). It is generally + /// not used in application code. + /// + /// + /// Do not construct instances of this class directly from either provider or application code as the + /// constructor signature may change as new dependencies are added. Instead, use this type in + /// your constructor so that an instance will be created and injected automatically by the + /// dependency injection container. To create an instance with some dependent services replaced, + /// first resolve the object from the dependency injection container, then replace selected + /// services using the 'With...' methods. Do not call the constructor at any point in this process. + /// + /// + /// The service lifetime is . This means that each + /// instance will use its own instance of this service. + /// The implementation may depend on other services registered with any lifetime. + /// The implementation does not need to be thread-safe. + /// + /// + public sealed class QueryCompilationContextDependencies + { + /// + /// + /// Creates the service dependencies parameter object for a . + /// + /// + /// Do not call this constructor directly from either provider or application code as it may change + /// as new dependencies are added. Instead, use this type in your constructor so that an instance + /// will be created and injected automatically by the dependency injection container. To create + /// an instance with some dependent services replaced, first resolve the object from the dependency + /// injection container, then replace selected services using the 'With...' methods. Do not call + /// the constructor at any point in this process. + /// + /// + /// 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. + /// + /// + [EntityFrameworkInternal] + public QueryCompilationContextDependencies( + [NotNull] IModel model, + [NotNull] IQueryOptimizerFactory queryOptimizerFactory, + [NotNull] IQueryableMethodTranslatingExpressionVisitorFactory queryableMethodTranslatingExpressionVisitorFactory, + [NotNull] IShapedQueryOptimizerFactory shapedQueryOptimizerFactory, + [NotNull] IShapedQueryCompilingExpressionVisitorFactory shapedQueryCompilingExpressionVisitorFactory, + [NotNull] ICurrentDbContext currentContext, + [NotNull] IDbContextOptions contextOptions, + [NotNull] IDiagnosticsLogger logger) + { + Check.NotNull(model, nameof(model)); + Check.NotNull(queryOptimizerFactory, nameof(queryOptimizerFactory)); + Check.NotNull(queryableMethodTranslatingExpressionVisitorFactory, nameof(queryableMethodTranslatingExpressionVisitorFactory)); + Check.NotNull(shapedQueryOptimizerFactory, nameof(shapedQueryOptimizerFactory)); + Check.NotNull(shapedQueryCompilingExpressionVisitorFactory, nameof(shapedQueryCompilingExpressionVisitorFactory)); + Check.NotNull(currentContext, nameof(currentContext)); + Check.NotNull(contextOptions, nameof(contextOptions)); + Check.NotNull(logger, nameof(logger)); + + CurrentContext = currentContext; + Model = model; + QueryOptimizerFactory = queryOptimizerFactory; + QueryableMethodTranslatingExpressionVisitorFactory = queryableMethodTranslatingExpressionVisitorFactory; + ShapedQueryOptimizerFactory = shapedQueryOptimizerFactory; + ShapedQueryCompilingExpressionVisitorFactory = shapedQueryCompilingExpressionVisitorFactory; + ContextOptions = contextOptions; + Logger = logger; + } + + /// + /// The cache being used to store value generator instances. + /// + public ICurrentDbContext CurrentContext { get; } + + /// + /// The model. + /// + public IModel Model { get; } + + /// + /// The query optimizer factory. + /// + public IQueryOptimizerFactory QueryOptimizerFactory { get; } + + /// + /// The queryable method-translating expression visitor factory. + /// + public IQueryableMethodTranslatingExpressionVisitorFactory QueryableMethodTranslatingExpressionVisitorFactory { get; } + + /// + /// The shaped-query optimizer factory + /// + public IShapedQueryOptimizerFactory ShapedQueryOptimizerFactory { get; } + + /// + /// The shaped-query compiling expression visitor factory. + /// + public IShapedQueryCompilingExpressionVisitorFactory ShapedQueryCompilingExpressionVisitorFactory { get; } + + /// + /// The context options. + /// + public IDbContextOptions ContextOptions { get; } + + /// + /// The logger. + /// + public IDiagnosticsLogger Logger { get; } + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With([NotNull] IModel model) + => new QueryCompilationContextDependencies( + model, + QueryOptimizerFactory, + QueryableMethodTranslatingExpressionVisitorFactory, + ShapedQueryOptimizerFactory, + ShapedQueryCompilingExpressionVisitorFactory, + CurrentContext, + ContextOptions, + Logger); + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With([NotNull] IQueryOptimizerFactory queryOptimizerFactory) + => new QueryCompilationContextDependencies( + Model, + queryOptimizerFactory, + QueryableMethodTranslatingExpressionVisitorFactory, + ShapedQueryOptimizerFactory, + ShapedQueryCompilingExpressionVisitorFactory, + CurrentContext, + ContextOptions, + Logger); + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With( + [NotNull] IQueryableMethodTranslatingExpressionVisitorFactory queryableMethodTranslatingExpressionVisitorFactory) + => new QueryCompilationContextDependencies( + Model, + QueryOptimizerFactory, + queryableMethodTranslatingExpressionVisitorFactory, + ShapedQueryOptimizerFactory, + ShapedQueryCompilingExpressionVisitorFactory, + CurrentContext, + ContextOptions, + Logger); + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With([NotNull] IShapedQueryOptimizerFactory shapedQueryOptimizerFactory) + => new QueryCompilationContextDependencies( + Model, + QueryOptimizerFactory, + QueryableMethodTranslatingExpressionVisitorFactory, + shapedQueryOptimizerFactory, + ShapedQueryCompilingExpressionVisitorFactory, + CurrentContext, + ContextOptions, + Logger); + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With( + [NotNull] IShapedQueryCompilingExpressionVisitorFactory shapedQueryCompilingExpressionVisitorFactory) + => new QueryCompilationContextDependencies( + Model, + QueryOptimizerFactory, + QueryableMethodTranslatingExpressionVisitorFactory, + ShapedQueryOptimizerFactory, + shapedQueryCompilingExpressionVisitorFactory, + CurrentContext, + ContextOptions, + Logger); + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With([NotNull] ICurrentDbContext currentContext) + => new QueryCompilationContextDependencies( + Model, + QueryOptimizerFactory, + QueryableMethodTranslatingExpressionVisitorFactory, + ShapedQueryOptimizerFactory, + ShapedQueryCompilingExpressionVisitorFactory, + currentContext, + ContextOptions, + Logger); + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With([NotNull] IDbContextOptions contextOptions) + => new QueryCompilationContextDependencies( + Model, + QueryOptimizerFactory, + QueryableMethodTranslatingExpressionVisitorFactory, + ShapedQueryOptimizerFactory, + ShapedQueryCompilingExpressionVisitorFactory, + CurrentContext, + contextOptions, + Logger); + + /// + /// Clones this dependency parameter object with one service replaced. + /// + /// A replacement for the current dependency of this type. + /// A new parameter object with the given service replaced. + public QueryCompilationContextDependencies With([NotNull] IDiagnosticsLogger logger) + => new QueryCompilationContextDependencies( + Model, + QueryOptimizerFactory, + QueryableMethodTranslatingExpressionVisitorFactory, + ShapedQueryOptimizerFactory, + ShapedQueryCompilingExpressionVisitorFactory, + CurrentContext, + ContextOptions, + logger); + } +} diff --git a/src/EFCore/Query/ShapedQueryExpression.cs b/src/EFCore/Query/ShapedQueryExpression.cs index c4fdb4abf6f..741963e8048 100644 --- a/src/EFCore/Query/ShapedQueryExpression.cs +++ b/src/EFCore/Query/ShapedQueryExpression.cs @@ -19,7 +19,7 @@ public ShapedQueryExpression(Expression queryExpression, Expression shaperExpres public virtual ResultCardinality ResultCardinality { get; set; } public virtual Expression ShaperExpression { get; set; } public override Type Type => typeof(IQueryable<>).MakeGenericType(ShaperExpression.Type); - public override ExpressionType NodeType => ExpressionType.Extension; + public sealed override ExpressionType NodeType => ExpressionType.Extension; public override bool CanReduce => false; protected override Expression VisitChildren(ExpressionVisitor visitor) diff --git a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs index 8b49feeb506..c649cca97c8 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs @@ -213,12 +213,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasName("GetReportingPeriodStartDate"); var isDateMethodInfo = typeof(UDFSqlContext).GetMethod(nameof(IsDateStatic)); modelBuilder.HasDbFunction(isDateMethodInfo) - .HasTranslation(args => new SqlFunctionExpression("IsDate", args, isDateMethodInfo.ReturnType, null)); + .HasTranslation(args => SqlFunctionExpression.Create("IsDate", args, isDateMethodInfo.ReturnType, null)); var methodInfo = typeof(UDFSqlContext).GetMethod(nameof(MyCustomLengthStatic)); modelBuilder.HasDbFunction(methodInfo) - .HasTranslation(args => new SqlFunctionExpression("len", args, methodInfo.ReturnType, null)); + .HasTranslation(args => SqlFunctionExpression.Create("len", args, methodInfo.ReturnType, null)); //Instance modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(CustomerOrderCountInstance))) @@ -233,14 +233,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasName("GetReportingPeriodStartDate"); var isDateMethodInfo2 = typeof(UDFSqlContext).GetMethod(nameof(IsDateInstance)); modelBuilder.HasDbFunction(isDateMethodInfo2) - .HasTranslation(args => new SqlFunctionExpression("IsDate", args, isDateMethodInfo2.ReturnType, null)); + .HasTranslation(args => SqlFunctionExpression.Create("IsDate", args, isDateMethodInfo2.ReturnType, null)); modelBuilder.HasDbFunction(typeof(UDFSqlContext).GetMethod(nameof(DollarValueInstance))).HasName("DollarValue"); var methodInfo2 = typeof(UDFSqlContext).GetMethod(nameof(MyCustomLengthInstance)); modelBuilder.HasDbFunction(methodInfo2) - .HasTranslation(args => new SqlFunctionExpression("len", args, methodInfo2.ReturnType, null)); + .HasTranslation(args => SqlFunctionExpression.Create("len", args, methodInfo2.ReturnType, null)); } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs index 2e0f0c4d625..5a11c98316e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs @@ -34,7 +34,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.HasDbFunction( typeof(GeoExtensions).GetMethod(nameof(GeoExtensions.Distance)), b => b.HasTranslation( - e => new SqlFunctionExpression( + e => SqlFunctionExpression.Create( e.First(), "STDistance", e.Skip(1), diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs b/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs index e23522cc5bc..b64ce5f34bf 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs @@ -37,7 +37,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.HasDbFunction( typeof(GeoExtensions).GetMethod(nameof(GeoExtensions.Distance)), b => b.HasTranslation( - e => new SqlFunctionExpression( + e => SqlFunctionExpression.Create( "Distance", e, typeof(double), diff --git a/test/EFCore.Tests/ApiConsistencyTestBase.cs b/test/EFCore.Tests/ApiConsistencyTestBase.cs index 225209add5b..607ebe5c284 100644 --- a/test/EFCore.Tests/ApiConsistencyTestBase.cs +++ b/test/EFCore.Tests/ApiConsistencyTestBase.cs @@ -93,6 +93,7 @@ from method in type.GetMethods(AnyInstance) && !(method.IsVirtual && !method.IsFinal) && !method.Name.StartsWith("add_", StringComparison.Ordinal) && !method.Name.StartsWith("remove_", StringComparison.Ordinal) + && !method.Name.Equals("get_NodeType", StringComparison.Ordinal) && (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly) && method.Name != "GenerateCacheKeyCore" select type.FullName + "." + method.Name) diff --git a/test/EFCore.Tests/Query/QueryCompilationContextDependenciesTest.cs b/test/EFCore.Tests/Query/QueryCompilationContextDependenciesTest.cs new file mode 100644 index 00000000000..0f54c5a15f1 --- /dev/null +++ b/test/EFCore.Tests/Query/QueryCompilationContextDependenciesTest.cs @@ -0,0 +1,17 @@ +// 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 Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public class QueryCompilationContextDependenciesTest + { + [ConditionalFact] + public void Can_use_With_methods_to_clone_and_replace_service() + { + InMemoryTestHelpers.Instance.TestDependenciesClone(); + } + } +}