diff --git a/src/EFCore.Abstractions/DbFunctionAttribute.cs b/src/EFCore.Abstractions/DbFunctionAttribute.cs index b78c8e76c3f..006df50089e 100644 --- a/src/EFCore.Abstractions/DbFunctionAttribute.cs +++ b/src/EFCore.Abstractions/DbFunctionAttribute.cs @@ -17,7 +17,7 @@ namespace Microsoft.EntityFrameworkCore public class DbFunctionAttribute : Attribute #pragma warning restore CA1813 // Avoid unsealed attributes { - private string _functionName; + private string _name; private string _schema; /// @@ -30,28 +30,28 @@ public DbFunctionAttribute() /// /// Initializes a new instance of the class. /// - /// The name of the function in the database. + /// The name of the function in the database. /// The schema of the function in the database. - public DbFunctionAttribute([NotNull] string functionName, [CanBeNull] string schema = null) + public DbFunctionAttribute([NotNull] string name, [CanBeNull] string schema = null) { - Check.NotEmpty(functionName, nameof(functionName)); + Check.NotEmpty(name, nameof(name)); - _functionName = functionName; + _name = name; _schema = schema; } /// /// The name of the function in the database. /// - public virtual string FunctionName + public virtual string Name { - get => _functionName; + get => _name; [param: NotNull] set { Check.NotEmpty(value, nameof(value)); - _functionName = value; + _name = value; } } diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs index 7ec4065ce9d..0c61b6c35d2 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs @@ -6,7 +6,7 @@ using System.Reflection; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Utilities; diff --git a/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs index 627c147e57b..b2cdd34dbd9 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs @@ -13,7 +13,6 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index f740131a629..b1e0f6f8f1f 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -1,8 +1,8 @@ // 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.Collections; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; @@ -37,13 +37,24 @@ public virtual void ProcessEntityTypeAdded( var entityType = entityTypeBuilder.Metadata; if (entityTypeBuilder.Metadata.BaseType == null - && !entityTypeBuilder.Metadata.GetDerivedTypes().Any()) + && !Any(entityTypeBuilder.Metadata.GetDerivedTypes())) { entityTypeBuilder.HasDiscriminator(typeof(string)) .HasValue(entityType, entityType.ShortName()); } } + private static bool Any([NotNull] IEnumerable source) + { + foreach (var _ in source) + { + return true; + } + + return false; + } + + /// /// Called after the base type of an entity type changes. /// diff --git a/src/EFCore.Cosmos/Query/Internal/CaseExpression.cs b/src/EFCore.Cosmos/Query/Internal/CaseExpression.cs index fe94df92a82..db86d6728c3 100644 --- a/src/EFCore.Cosmos/Query/Internal/CaseExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/CaseExpression.cs @@ -3,7 +3,7 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs b/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs index cc79c19df03..8d57bc4bb73 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs @@ -59,7 +59,7 @@ public virtual SqlExpression Translate(IModel model, SqlExpression instance, Met // arguments.Select(e => _sqlExpressionFactory.ApplyDefaultTypeMapping(e)).ToList()) // ?? _sqlExpressionFactory.Function( // dbFunction.Schema, - // dbFunction.FunctionName, + // dbFunction.Name, // arguments, // method.ReturnType); //} diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs index 9ee15cbf470..1e5b06aa28a 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs @@ -8,9 +8,6 @@ using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -312,7 +309,7 @@ protected override Expression VisitNew(NewExpression newExpression) } else { - var projectionMember = _projectionMembers.Peek().AddMember(newExpression.Members[i]); + var projectionMember = _projectionMembers.Peek().Append(newExpression.Members[i]); _projectionMembers.Push(projectionMember); newArguments[i] = Visit(newExpression.Arguments[i]); if (newArguments[i] == null) @@ -350,7 +347,7 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp } else { - var projectionMember = _projectionMembers.Peek().AddMember(memberAssignment.Member); + var projectionMember = _projectionMembers.Peek().Append(memberAssignment.Member); _projectionMembers.Push(projectionMember); var visitedExpression = Visit(memberAssignment.Expression); diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs index 8abbbca739e..4796391b719 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs @@ -6,8 +6,7 @@ using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs index 0276ccb636d..6732a77a209 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs index 6b0f7eedcc7..45bf36ab143 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs @@ -11,7 +11,6 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Cosmos.Query.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; @@ -19,9 +18,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; using Newtonsoft.Json.Linq; @@ -75,7 +71,7 @@ protected override Expression VisitShapedQueryExpression(ShapedQueryExpression s shaperBody = new JObjectInjectingExpressionVisitor() .Visit(shaperBody); shaperBody = InjectEntityMaterializers(shaperBody); - shaperBody = new CosmosProjectionBindingRemovingExpressionVisitor(selectExpression, jObjectParameter, TrackQueryResults) + shaperBody = new CosmosProjectionBindingRemovingExpressionVisitor(selectExpression, jObjectParameter, IsTracking) .Visit(shaperBody); var shaperLambda = Expression.Lambda( @@ -84,7 +80,7 @@ protected override Expression VisitShapedQueryExpression(ShapedQueryExpression s jObjectParameter); return Expression.New( - (Async + (IsAsync ? typeof(AsyncQueryingEnumerable<>) : typeof(QueryingEnumerable<>)).MakeGenericType(shaperLambda.ReturnType).GetConstructors()[0], Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(CosmosQueryContext)), @@ -951,7 +947,7 @@ public override Expression Visit(Expression expression) ? _sqlExpressionFactory.In( (SqlExpression)Visit(inExpression.Item), _sqlExpressionFactory.Constant(inValues, typeMapping), - inExpression.Negated) + inExpression.IsNegated) : null; var nullCheckExpression = hasNullValue diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs index a9e498ecc97..483ddf075eb 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitorFactory.cs @@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Pipeline; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs index d861cbbb2d2..f62f73852e1 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs @@ -5,11 +5,9 @@ using System.Diagnostics; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs index d565dfb693b..d6db258d65a 100644 --- a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs @@ -7,8 +7,7 @@ using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/InExpression.cs b/src/EFCore.Cosmos/Query/Internal/InExpression.cs index 00bca1a5bcf..daad1444353 100644 --- a/src/EFCore.Cosmos/Query/Internal/InExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/InExpression.cs @@ -3,7 +3,7 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -26,7 +26,7 @@ public InExpression(SqlExpression item, bool negated, SqlExpression values, Core : base(typeof(bool), typeMapping) { Item = item; - Negated = negated; + IsNegated = negated; Values = values; } @@ -44,7 +44,7 @@ public InExpression(SqlExpression item, bool negated, SqlExpression values, Core /// 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 bool Negated { get; } + public virtual bool IsNegated { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -74,7 +74,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 virtual InExpression Negate() => new InExpression(Item, !Negated, Values, TypeMapping); + public virtual InExpression Negate() => new InExpression(Item, !IsNegated, Values, TypeMapping); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -84,7 +84,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// public virtual InExpression Update(SqlExpression item, SqlExpression values) => item != Item || values != Values - ? new InExpression(item, Negated, values, TypeMapping) + ? new InExpression(item, IsNegated, values, TypeMapping) : this; /// @@ -96,7 +96,7 @@ public virtual InExpression Update(SqlExpression item, SqlExpression values) public override void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.Visit(Item); - expressionPrinter.StringBuilder.Append(Negated ? " NOT IN " : " IN "); + expressionPrinter.StringBuilder.Append(IsNegated ? " NOT IN " : " IN "); expressionPrinter.StringBuilder.Append("("); expressionPrinter.Visit(Values); expressionPrinter.StringBuilder.Append(")"); @@ -117,7 +117,7 @@ public override bool Equals(object obj) private bool Equals(InExpression inExpression) => base.Equals(inExpression) && Item.Equals(inExpression.Item) - && Negated.Equals(inExpression.Negated) + && IsNegated.Equals(inExpression.IsNegated) && (Values == null ? inExpression.Values == null : Values.Equals(inExpression.Values)); /// @@ -126,6 +126,6 @@ private bool Equals(InExpression inExpression) /// 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 int GetHashCode() => HashCode.Combine(base.GetHashCode(), Item, Negated, Values); + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Item, IsNegated, Values); } } diff --git a/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs b/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs index b13f4bb5a24..9ab08e217fe 100644 --- a/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs @@ -4,7 +4,7 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs b/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs index b8d2dbd2fef..6bb460e498a 100644 --- a/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs @@ -4,8 +4,7 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs index 464e2022670..1fca00fc72f 100644 --- a/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ObjectArrayProjectionExpression.cs @@ -5,8 +5,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs b/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs index 6e59b83edd7..23493b261ca 100644 --- a/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs @@ -3,8 +3,7 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { @@ -25,7 +24,7 @@ public class OrderingExpression : Expression, IPrintable public OrderingExpression(SqlExpression expression, bool ascending) { Expression = expression; - Ascending = ascending; + IsAscending = ascending; } /// @@ -42,7 +41,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 virtual bool Ascending { get; } + public virtual bool IsAscending { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -77,7 +76,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// public virtual OrderingExpression Update(SqlExpression expression) => expression != Expression - ? new OrderingExpression(expression, Ascending) + ? new OrderingExpression(expression, IsAscending) : this; /// @@ -90,7 +89,7 @@ public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.Visit(Expression); - expressionPrinter.StringBuilder.Append(Ascending ? " ASC" : " DESC"); + expressionPrinter.StringBuilder.Append(IsAscending ? " ASC" : " DESC"); } /// @@ -107,7 +106,7 @@ public override bool Equals(object obj) private bool Equals(OrderingExpression orderingExpression) => Expression.Equals(orderingExpression.Expression) - && Ascending == orderingExpression.Ascending; + && IsAscending == orderingExpression.IsAscending; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -115,6 +114,6 @@ private bool Equals(OrderingExpression orderingExpression) /// 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 int GetHashCode() => HashCode.Combine(Expression, Ascending); + public override int GetHashCode() => HashCode.Combine(Expression, IsAscending); } } diff --git a/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs index e0e48717dbd..a5842c345be 100644 --- a/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/ProjectionExpression.cs @@ -3,8 +3,7 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal { diff --git a/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs b/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs index 4bd89230bee..43f8c6fbe2b 100644 --- a/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs +++ b/src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs @@ -238,7 +238,7 @@ protected override Expression VisitOrdering(OrderingExpression orderingExpressio { Visit(orderingExpression.Expression); - if (!orderingExpression.Ascending) + if (!orderingExpression.IsAscending) { _sqlBuilder.Append(" DESC"); } @@ -396,7 +396,7 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame protected override Expression VisitIn(InExpression inExpression) { Visit(inExpression.Item); - _sqlBuilder.Append(inExpression.Negated ? " NOT IN " : " IN "); + _sqlBuilder.Append(inExpression.IsNegated ? " NOT IN " : " IN "); _sqlBuilder.Append("("); var valuesConstant = (SqlConstantExpression)inExpression.Values; var valuesList = ((IEnumerable)valuesConstant.Value) @@ -415,7 +415,7 @@ protected override Expression VisitIn(InExpression inExpression) /// protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression) { - _sqlBuilder.Append(sqlFunctionExpression.FunctionName); + _sqlBuilder.Append(sqlFunctionExpression.Name); _sqlBuilder.Append("("); GenerateList(sqlFunctionExpression.Arguments, e => Visit(e)); _sqlBuilder.Append(")"); diff --git a/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs b/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs index 8ff3ecb2957..083669eef27 100644 --- a/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SelectExpression.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Newtonsoft.Json.Linq; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -143,7 +143,7 @@ public virtual void ApplyProjection() { result[keyValuePair.Key] = Constant(AddToProjection( keyValuePair.Value, - keyValuePair.Key.LastMember?.Name)); + keyValuePair.Key.Last?.Name)); } _projectionMapping = result; @@ -347,7 +347,7 @@ public virtual void ReverseOrderings() _orderings.Add( new OrderingExpression( existingOrdering.Expression, - !existingOrdering.Ascending)); + !existingOrdering.IsAscending)); } } diff --git a/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs index cb445c121df..d4d93cdb60d 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlBinaryExpression.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; diff --git a/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs index d5fb121a6b6..36e850fdc80 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlConstantExpression.cs @@ -5,7 +5,7 @@ using System.Collections; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs index ea8b4edea62..cf1dde8862b 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlExpression.cs @@ -3,8 +3,7 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs index 6d3af559a1f..8c313beae33 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs @@ -6,8 +6,7 @@ using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal diff --git a/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs index fa6d9da0d87..6804d20b98d 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlFunctionExpression.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal @@ -19,13 +19,13 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal public class SqlFunctionExpression : SqlExpression { public SqlFunctionExpression( - string functionName, + string name, IEnumerable arguments, Type type, CoreTypeMapping typeMapping) : base(type, typeMapping) { - FunctionName = functionName; + Name = name; Arguments = (arguments ?? Array.Empty()).ToList(); } @@ -35,7 +35,7 @@ public SqlFunctionExpression( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual string FunctionName { get; } + public virtual string Name { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -63,7 +63,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return changed ? new SqlFunctionExpression( - FunctionName, + Name, arguments, Type, TypeMapping) @@ -78,7 +78,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// public virtual SqlFunctionExpression ApplyTypeMapping(CoreTypeMapping typeMapping) => new SqlFunctionExpression( - FunctionName, + Name, Arguments, Type, typeMapping ?? TypeMapping); @@ -91,7 +91,7 @@ public virtual SqlFunctionExpression ApplyTypeMapping(CoreTypeMapping typeMappin /// public virtual SqlFunctionExpression Update(IReadOnlyList arguments) => !arguments.SequenceEqual(Arguments) - ? new SqlFunctionExpression(FunctionName, arguments, Type, TypeMapping) + ? new SqlFunctionExpression(Name, arguments, Type, TypeMapping) : this; /// @@ -102,7 +102,7 @@ public virtual SqlFunctionExpression Update(IReadOnlyList argumen /// public override void Print(ExpressionPrinter expressionPrinter) { - expressionPrinter.StringBuilder.Append(FunctionName); + expressionPrinter.StringBuilder.Append(Name); expressionPrinter.StringBuilder.Append("("); expressionPrinter.VisitList(Arguments); expressionPrinter.StringBuilder.Append(")"); @@ -122,7 +122,7 @@ public override bool Equals(object obj) private bool Equals(SqlFunctionExpression sqlFunctionExpression) => base.Equals(sqlFunctionExpression) - && string.Equals(FunctionName, sqlFunctionExpression.FunctionName) + && string.Equals(Name, sqlFunctionExpression.Name) && Arguments.SequenceEqual(sqlFunctionExpression.Arguments); /// @@ -135,7 +135,7 @@ public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); - hash.Add(FunctionName); + hash.Add(Name); for (var i = 0; i < Arguments.Count; i++) { hash.Add(Arguments[i]); diff --git a/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs index ce5f932a2ac..1ce4d4f69ad 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlParameterExpression.cs @@ -3,7 +3,7 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal diff --git a/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs b/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs index 082c802145b..cb47ae61f12 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlUnaryExpression.cs @@ -3,9 +3,8 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; diff --git a/src/EFCore.Cosmos/Query/Internal/ValueBufferFactoryFactory.cs b/src/EFCore.Cosmos/Query/Internal/ValueBufferFactoryFactory.cs index 2bbd0619063..e595d685901 100644 --- a/src/EFCore.Cosmos/Query/Internal/ValueBufferFactoryFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/ValueBufferFactoryFactory.cs @@ -8,7 +8,7 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Conventions; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Newtonsoft.Json.Linq; namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs index e7746455f3e..8e751512936 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs @@ -16,8 +16,8 @@ using Microsoft.EntityFrameworkCore.Cosmos.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs index 77619d21cc0..a5efefa9c7e 100644 --- a/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs @@ -5,7 +5,7 @@ using JetBrains.Annotations; using Microsoft.Azure.Cosmos; using Microsoft.EntityFrameworkCore.Cosmos.Infrastructure.Internal; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal diff --git a/src/EFCore.Design/Design/OperationExecutor.cs b/src/EFCore.Design/Design/OperationExecutor.cs index 1c272e1012f..68c34b80ec8 100644 --- a/src/EFCore.Design/Design/OperationExecutor.cs +++ b/src/EFCore.Design/Design/OperationExecutor.cs @@ -8,6 +8,7 @@ using System.Reflection; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Design.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Utilities; diff --git a/src/EFCore.Design/Migrations/Design/CSharpMigrationsGeneratorDependencies.cs b/src/EFCore.Design/Migrations/Design/CSharpMigrationsGeneratorDependencies.cs index fb63bae159c..16994d34dc4 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpMigrationsGeneratorDependencies.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpMigrationsGeneratorDependencies.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.Migrations.Design { @@ -37,10 +38,14 @@ public sealed class CSharpMigrationsGeneratorDependencies /// 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. + /// /// - /// The C# helper. - /// The C# migration operation generator. - /// The C# model snapshot generator. + [EntityFrameworkInternal] public CSharpMigrationsGeneratorDependencies( [NotNull] ICSharpHelper csharpHelper, [NotNull] ICSharpMigrationOperationGenerator csharpMigrationOperationGenerator, diff --git a/src/EFCore.Design/Migrations/Design/MigrationsCodeGeneratorDependencies.cs b/src/EFCore.Design/Migrations/Design/MigrationsCodeGeneratorDependencies.cs index 8eae513580d..ac74b871ea5 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsCodeGeneratorDependencies.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsCodeGeneratorDependencies.cs @@ -1,6 +1,8 @@ // 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.Infrastructure; + namespace Microsoft.EntityFrameworkCore.Migrations.Design { /// @@ -34,8 +36,14 @@ public sealed class MigrationsCodeGeneratorDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public MigrationsCodeGeneratorDependencies() { } diff --git a/src/EFCore.Design/Migrations/Design/MigrationsScaffolderDependencies.cs b/src/EFCore.Design/Migrations/Design/MigrationsScaffolderDependencies.cs index 4163016635a..99b944224c9 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsScaffolderDependencies.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsScaffolderDependencies.cs @@ -48,18 +48,13 @@ public sealed class MigrationsScaffolderDependencies /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// /// - /// The current DbContext. - /// The model. - /// The migrations assembly. - /// The migrations model differ. - /// The migrations ID generator. - /// The migrations code generator selector. - /// The history repository. - /// The operation reporter. - /// The database provider. - /// The snapshot model processor. - /// The migrator. [EntityFrameworkInternal] public MigrationsScaffolderDependencies( [NotNull] ICurrentDbContext currentContext, diff --git a/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs b/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs index fb9c2a95454..d81ec15d060 100644 --- a/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs +++ b/src/EFCore.Design/Scaffolding/ModelCodeGeneratorDependencies.cs @@ -1,6 +1,8 @@ // 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.Infrastructure; + namespace Microsoft.EntityFrameworkCore.Scaffolding { /// @@ -34,8 +36,14 @@ public sealed class ModelCodeGeneratorDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public ModelCodeGeneratorDependencies() { } diff --git a/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs b/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs index d018e703efb..f5d0ab4580b 100644 --- a/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs +++ b/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs @@ -9,12 +9,10 @@ using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.InMemory.Metadata.Conventions; using Microsoft.EntityFrameworkCore.InMemory.Query.Internal; -using Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline; using Microsoft.EntityFrameworkCore.InMemory.Storage.Internal; using Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.EntityFrameworkCore.ValueGeneration; diff --git a/src/EFCore.InMemory/Query/Pipeline/EntityValuesExpression.cs b/src/EFCore.InMemory/Query/Internal/EntityValuesExpression.cs similarity index 87% rename from src/EFCore.InMemory/Query/Pipeline/EntityValuesExpression.cs rename to src/EFCore.InMemory/Query/Internal/EntityValuesExpression.cs index e3b9ef3551c..8c74cbfc78d 100644 --- a/src/EFCore.InMemory/Query/Pipeline/EntityValuesExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/EntityValuesExpression.cs @@ -6,7 +6,7 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class EntityProjectionExpression : Expression { @@ -19,11 +19,11 @@ public EntityProjectionExpression( _readExpressionMap = readExpressionMap; } - public IEntityType EntityType { get; } + public virtual IEntityType EntityType { get; } public override Type Type => EntityType.ClrType; public override ExpressionType NodeType => ExpressionType.Extension; - public Expression BindProperty(IProperty property) + public virtual Expression BindProperty(IProperty property) { if (!EntityType.IsAssignableFrom(property.DeclaringEntityType) && !property.DeclaringEntityType.IsAssignableFrom(EntityType)) diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs similarity index 96% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryExpressionTranslatingExpressionVisitor.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index 97412f5730a..daea27056f4 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -6,19 +6,18 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryExpressionTranslatingExpressionVisitor : ExpressionVisitor { + private const string CompiledQueryParameterPrefix = "__"; + private readonly QueryableMethodTranslatingExpressionVisitor _queryableMethodTranslatingExpressionVisitor; public InMemoryExpressionTranslatingExpressionVisitor( @@ -27,7 +26,7 @@ public InMemoryExpressionTranslatingExpressionVisitor( _queryableMethodTranslatingExpressionVisitor = queryableMethodTranslatingExpressionVisitor; } - public Expression Translate(Expression expression) + public virtual Expression Translate(Expression expression) { return Visit(expression); } @@ -101,7 +100,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (subqueryTranslation != null) { var subquery = (InMemoryQueryExpression)subqueryTranslation.QueryExpression; - if (subqueryTranslation.ResultType == ResultType.Enumerable) + if (subqueryTranslation.ResultCardinality == ResultCardinality.Enumerable) { return null; } @@ -261,7 +260,7 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitParameter(ParameterExpression parameterExpression) { - if (parameterExpression.Name.StartsWith(CompiledQueryCache.CompiledQueryParameterPrefix)) + if (parameterExpression.Name.StartsWith(CompiledQueryParameterPrefix, StringComparison.Ordinal)) { return Expression.Call( _getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type), diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryLinqOperatorProvider.cs b/src/EFCore.InMemory/Query/Internal/InMemoryLinqOperatorProvider.cs similarity index 98% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryLinqOperatorProvider.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryLinqOperatorProvider.cs index 5e745a298b7..1123e91f34f 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryLinqOperatorProvider.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryLinqOperatorProvider.cs @@ -7,7 +7,7 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public static class InMemoryLinqOperatorProvider { diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryProjectionBindingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs similarity index 96% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryProjectionBindingExpressionVisitor.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs index a2ee08970b3..1b9acd5edfd 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs @@ -5,11 +5,11 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryProjectionBindingExpressionVisitor : ExpressionVisitor { @@ -30,7 +30,7 @@ public InMemoryProjectionBindingExpressionVisitor( _expressionTranslatingExpressionVisitor = expressionTranslatingExpressionVisitor; } - public Expression Translate(InMemoryQueryExpression queryExpression, Expression expression) + public virtual Expression Translate(InMemoryQueryExpression queryExpression, Expression expression) { _queryExpression = queryExpression; _clientEval = false; @@ -193,7 +193,7 @@ protected override Expression VisitNew(NewExpression newExpression) } else { - var projectionMember = _projectionMembers.Peek().AddMember(newExpression.Members[i]); + var projectionMember = _projectionMembers.Peek().Append(newExpression.Members[i]); _projectionMembers.Push(projectionMember); newArguments[i] = Visit(newExpression.Arguments[i]); if (newArguments[i] == null) @@ -225,7 +225,7 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp } else { - var projectionMember = _projectionMembers.Peek().AddMember(memberAssignment.Member); + var projectionMember = _projectionMembers.Peek().Append(memberAssignment.Member); _projectionMembers.Push(projectionMember); var visitedExpression = Visit(memberAssignment.Expression); diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs similarity index 93% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryQueryExpression.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index aa6500c1c5e..2394530b8b9 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -10,11 +10,10 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryQueryExpression : Expression { @@ -24,7 +23,7 @@ private static readonly ConstructorInfo _valueBufferConstructor private readonly List _valueBufferSlots = new List(); private IDictionary _projectionMapping = new Dictionary(); - public IReadOnlyList Projection => _valueBufferSlots; + public virtual IReadOnlyList Projection => _valueBufferSlots; private readonly IDictionary> _entityProjectionCache = new Dictionary>(); @@ -99,7 +98,7 @@ public InMemoryQueryExpression(IEntityType entityType) _projectionMapping[new ProjectionMember()] = entityProjection; } - public Expression GetSingleScalarProjection() + public virtual Expression GetSingleScalarProjection() { var expression = CreateReadValueExpression(ServerQueryExpression.Type, 0, null); _projectionMapping.Clear(); @@ -110,7 +109,7 @@ public Expression GetSingleScalarProjection() return new ProjectionBindingExpression(this, new ProjectionMember(), expression.Type); } - public void ConvertToEnumerable() + public virtual void ConvertToEnumerable() { if (ServerQueryExpression.Type.TryGetSequenceType() == null) { @@ -137,7 +136,7 @@ public void ConvertToEnumerable() } } - public void ReplaceProjectionMapping(IDictionary projectionMappings) + public virtual void ReplaceProjectionMapping(IDictionary projectionMappings) { _projectionMapping.Clear(); foreach (var kvp in projectionMappings) @@ -146,7 +145,7 @@ public void ReplaceProjectionMapping(IDictionary p } } - public IDictionary AddToProjection(EntityProjectionExpression entityProjectionExpression) + public virtual IDictionary AddToProjection(EntityProjectionExpression entityProjectionExpression) { if (!_entityProjectionCache.TryGetValue(entityProjectionExpression, out var indexMap)) { @@ -162,7 +161,7 @@ public IDictionary AddToProjection(EntityProjectionExpression en return indexMap; } - public int AddToProjection(Expression expression) + public virtual int AddToProjection(Expression expression) { _valueBufferSlots.Add(expression); @@ -172,10 +171,10 @@ public int AddToProjection(Expression expression) private IEnumerable GetAllPropertiesInHierarchy(IEntityType entityType) => entityType.GetTypesInHierarchy().SelectMany(EntityTypeExtensions.GetDeclaredProperties); - public Expression GetMappedProjection(ProjectionMember member) + public virtual Expression GetMappedProjection(ProjectionMember member) => _projectionMapping[member]; - public void ApplyPendingSelector() + public virtual void ApplyPendingSelector() { var clientProjection = _valueBufferSlots.Count != 0; var result = new Dictionary(); @@ -243,7 +242,7 @@ private IPropertyBase InferPropertyFromInner(Expression expression) return null; } - public void ApplyServerProjection() + public virtual void ApplyServerProjection() { var result = new Dictionary(); foreach (var keyValuePair in _projectionMapping) @@ -281,8 +280,8 @@ public void ApplyServerProjection() selectorLambda); } - public Expression ServerQueryExpression { get; set; } - public ParameterExpression ValueBufferParameter { get; } + public virtual Expression ServerQueryExpression { get; set; } + public virtual ParameterExpression ValueBufferParameter { get; } public override Type Type => typeof(IEnumerable); public override ExpressionType NodeType => ExpressionType.Extension; @@ -296,7 +295,7 @@ private Expression CreateReadValueExpression( Constant(index), Constant(property, typeof(IPropertyBase))); - public void AddInnerJoin( + public virtual void AddInnerJoin( InMemoryQueryExpression innerQueryExpression, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, @@ -325,13 +324,13 @@ public void AddInnerJoin( resultValueBufferExpressions.Add(replacingVisitor.Visit(entityProjection.BindProperty(property))); readExpressionMap[property] = CreateReadValueExpression(property.ClrType, index++, property); } - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { resultValueBufferExpressions.Add(replacingVisitor.Visit(projection.Value)); - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = CreateReadValueExpression(projection.Value.Type, index++, InferPropertyFromInner(projection.Value)); } } @@ -347,13 +346,13 @@ public void AddInnerJoin( resultValueBufferExpressions.Add(replacingVisitor.Visit(entityProjection.BindProperty(property))); readExpressionMap[property] = CreateReadValueExpression(property.ClrType, index++, property); } - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { resultValueBufferExpressions.Add(replacingVisitor.Visit(projection.Value)); - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = CreateReadValueExpression(projection.Value.Type, index++, InferPropertyFromInner(projection.Value)); } } @@ -399,7 +398,7 @@ private TransparentIdentifier(TOuter outer, TInner inner) public readonly TInner Inner; } - public void AddLeftJoin( + public virtual void AddLeftJoin( InMemoryQueryExpression innerQueryExpression, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, @@ -457,14 +456,14 @@ public void AddLeftJoin( resultValueBufferExpressions.Add(replacedExpression); readExpressionMap[property] = CreateReadValueExpression(replacedExpression.Type, index++, property); } - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { var replacedExpression = replacingVisitor.Visit(projection.Value); resultValueBufferExpressions.Add(replacedExpression); - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = CreateReadValueExpression(replacedExpression.Type, index++, InferPropertyFromInner(projection.Value)); } } @@ -484,7 +483,7 @@ public void AddLeftJoin( resultValueBufferExpressions.Add(replacedExpression); readExpressionMap[property] = CreateReadValueExpression(replacedExpression.Type, index++, property); } - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else @@ -492,7 +491,7 @@ public void AddLeftJoin( var replacedExpression = replacingVisitor.Visit(projection.Value); replacedExpression = nullableReadValueExpressionVisitor.Visit(replacedExpression); resultValueBufferExpressions.Add(replacedExpression); - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = CreateReadValueExpression(replacedExpression.Type, index++, InferPropertyFromInner(projection.Value)); } } @@ -529,7 +528,7 @@ public void AddLeftJoin( _projectionMapping = projectionMapping; } - public void AddCrossJoin(InMemoryQueryExpression innerQueryExpression, Type transparentIdentifierType) + public virtual void AddCrossJoin(InMemoryQueryExpression innerQueryExpression, Type transparentIdentifierType) { var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(ValueBuffer), "inner"); @@ -554,13 +553,13 @@ public void AddCrossJoin(InMemoryQueryExpression innerQueryExpression, Type tran resultValueBufferExpressions.Add(replacingVisitor.Visit(entityProjection.BindProperty(property))); readExpressionMap[property] = CreateReadValueExpression(property.ClrType, index++, property); } - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { resultValueBufferExpressions.Add(replacingVisitor.Visit(projection.Value)); - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = CreateReadValueExpression(projection.Value.Type, index++, InferPropertyFromInner(projection.Value)); } } @@ -576,13 +575,13 @@ public void AddCrossJoin(InMemoryQueryExpression innerQueryExpression, Type tran resultValueBufferExpressions.Add(replacingVisitor.Visit(entityProjection.BindProperty(property))); readExpressionMap[property] = CreateReadValueExpression(property.ClrType, index++, property); } - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { resultValueBufferExpressions.Add(replacingVisitor.Visit(projection.Value)); - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = CreateReadValueExpression(projection.Value.Type, index++, InferPropertyFromInner(projection.Value)); } } diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs similarity index 98% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryQueryableMethodTranslatingExpressionVisitor.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index 6f44485e2ec..5c94db0b269 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -2,15 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryQueryableMethodTranslatingExpressionVisitor : QueryableMethodTranslatingExpressionVisitor { @@ -36,6 +35,9 @@ public InMemoryQueryableMethodTranslatingExpressionVisitor( _model = model; } + private static Type CreateTransparentIdentifierType(Type outerType, Type innerType) + => typeof(TransparentIdentifier<,>).MakeGenericType(outerType, innerType); + public override ShapedQueryExpression TranslateSubquery(Expression expression) { return (ShapedQueryExpression)new InMemoryQueryableMethodTranslatingExpressionVisitor( diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs similarity index 69% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs index 4591b7f5094..cbaa18fcf85 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -2,13 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryQueryableMethodTranslatingExpressionVisitorFactory : IQueryableMethodTranslatingExpressionVisitorFactory { - public QueryableMethodTranslatingExpressionVisitor Create(IModel model) + public virtual QueryableMethodTranslatingExpressionVisitor Create(IModel model) => new InMemoryQueryableMethodTranslatingExpressionVisitor(model); } } diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitor.cs similarity index 98% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitor.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitor.cs index ffade8e486b..5f3607ff398 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitor.cs @@ -10,15 +10,12 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.InMemory.Query.Internal; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryShapedQueryCompilingExpressionVisitor : ShapedQueryCompilingExpressionVisitor { @@ -71,7 +68,7 @@ protected override Expression VisitShapedQueryExpression(ShapedQueryExpression s inMemoryQueryExpression.ValueBufferParameter); return Expression.New( - (Async + (IsAsync ? typeof(AsyncQueryingEnumerable<>) : typeof(QueryingEnumerable<>)).MakeGenericType(shaperLambda.ReturnType).GetConstructors()[0], QueryCompilationContext.QueryContextParameter, diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitorFactory.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitorFactory.cs similarity index 79% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitorFactory.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitorFactory.cs index e4808cdb5c3..cafca00480c 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitorFactory.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitorFactory.cs @@ -3,9 +3,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryShapedQueryCompilingExpressionVisitorFactory : IShapedQueryCompilingExpressionVisitorFactory { @@ -16,7 +15,7 @@ public InMemoryShapedQueryCompilingExpressionVisitorFactory(IEntityMaterializerS _entityMaterializerSource = entityMaterializerSource; } - public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) + public virtual ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) { return new InMemoryShapedQueryCompilingExpressionVisitor( queryCompilationContext, diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryOptimizer.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryOptimizer.cs similarity index 78% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryOptimizer.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryOptimizer.cs index dbbc55d44d4..6bb2c2c5bff 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryOptimizer.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryOptimizer.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryShapedQueryOptimizer : ShapedQueryOptimizer { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryOptimizerFactory.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryOptimizerFactory.cs new file mode 100644 index 00000000000..25392ddd9a5 --- /dev/null +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryOptimizerFactory.cs @@ -0,0 +1,15 @@ +// 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.Query; + +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal +{ + public class InMemoryShapedQueryOptimizerFactory : IShapedQueryOptimizerFactory + { + public virtual ShapedQueryOptimizer Create(QueryCompilationContext queryCompilationContext) + { + return new InMemoryShapedQueryOptimizer(); + } + } +} diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryTableExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs similarity index 87% rename from src/EFCore.InMemory/Query/Pipeline/InMemoryTableExpression.cs rename to src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs index 6c607fbfdd8..02eb09b98b4 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryTableExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryTableExpression.cs @@ -7,7 +7,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { public class InMemoryTableExpression : Expression { @@ -18,7 +18,7 @@ public InMemoryTableExpression(IEntityType entityType) public override Type Type => typeof(IEnumerable); - public IEntityType EntityType { get; } + public virtual IEntityType EntityType { get; } public override ExpressionType NodeType => ExpressionType.Extension; diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryOptimizerFactory.cs b/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryOptimizerFactory.cs deleted file mode 100644 index 332f39a8a53..00000000000 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryOptimizerFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 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.Query.Pipeline; - -namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline -{ - public class InMemoryShapedQueryOptimizerFactory : ShapedQueryOptimizerFactory - { - public override ShapedQueryOptimizer Create(QueryCompilationContext queryCompilationContext) - { - return new InMemoryShapedQueryOptimizer(); - } - } -} diff --git a/src/EFCore.Relational/Design/AnnotationCodeGeneratorDependencies.cs b/src/EFCore.Relational/Design/AnnotationCodeGeneratorDependencies.cs index 068c6ca8841..f2fc01dc66b 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGeneratorDependencies.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGeneratorDependencies.cs @@ -1,6 +1,8 @@ // 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.Infrastructure; + namespace Microsoft.EntityFrameworkCore.Design { /// @@ -34,8 +36,14 @@ public sealed class AnnotationCodeGeneratorDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public AnnotationCodeGeneratorDependencies() { } diff --git a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs index ae73bf92f01..8500f374cbb 100644 --- a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs +++ b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs @@ -12,8 +12,6 @@ using Microsoft.EntityFrameworkCore.Migrations.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Update; @@ -182,6 +180,10 @@ public override EntityFrameworkServicesBuilder TryAddCoreServices() .AddDependencySingleton() .AddDependencySingleton() .AddDependencySingleton() + .AddDependencySingleton() + .AddDependencySingleton() + .AddDependencySingleton() + .AddDependencySingleton() .AddDependencyScoped() .AddDependencyScoped() .AddDependencyScoped() diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs index ebc13e5e6a7..9e55bf8945d 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs @@ -74,7 +74,7 @@ protected virtual void ValidateDbFunctions([NotNull] IModel model, [NotNull] IDi { var methodInfo = dbFunction.MethodInfo; - if (string.IsNullOrEmpty(dbFunction.FunctionName)) + if (string.IsNullOrEmpty(dbFunction.Name)) { throw new InvalidOperationException( RelationalStrings.DbFunctionNameEmpty(methodInfo.DisplayName())); diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidatorDependencies.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidatorDependencies.cs index a5165411243..a0acb96148d 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelValidatorDependencies.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidatorDependencies.cs @@ -49,8 +49,14 @@ public sealed class RelationalModelValidatorDependencies /// 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. + /// /// - /// The type mapper. + [EntityFrameworkInternal] public RelationalModelValidatorDependencies( [NotNull] IRelationalTypeMappingSource typeMappingSource) { diff --git a/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs b/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs index c4fa349b856..a15042090a9 100644 --- a/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs @@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.EntityFrameworkCore.Storage; @@ -51,7 +51,7 @@ public virtual DbFunctionBuilder HasName([NotNull] string name) { Check.NotEmpty(name, nameof(name)); - _function.FunctionName = name; + _function.Name = name; return this; } @@ -61,7 +61,7 @@ IConventionDbFunctionBuilder IConventionDbFunctionBuilder.HasName(string name, b { if (((IConventionDbFunctionBuilder)this).CanSetName(name, fromDataAnnotation)) { - ((IConventionDbFunction)_function).SetFunctionName(name, fromDataAnnotation); + ((IConventionDbFunction)_function).SetName(name, fromDataAnnotation); return this; } @@ -70,8 +70,8 @@ IConventionDbFunctionBuilder IConventionDbFunctionBuilder.HasName(string name, b /// bool IConventionDbFunctionBuilder.CanSetName(string name, bool fromDataAnnotation) - => Overrides(fromDataAnnotation, _function.GetFunctionNameConfigurationSource()) - || _function.FunctionName == name; + => Overrides(fromDataAnnotation, _function.GetNameConfigurationSource()) + || _function.Name == name; /// /// Sets the schema of the database function. diff --git a/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs b/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs index 70cc4c6b0bd..59288e58cdd 100644 --- a/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Metadata.Builders diff --git a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilderDependencies.cs b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilderDependencies.cs index e32a567074c..b4c2cf6057b 100644 --- a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilderDependencies.cs +++ b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilderDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure @@ -48,7 +49,14 @@ public sealed class RelationalConventionSetBuilderDependencies /// The implementation may depend on other services registered with any lifetime. /// The implementation does not need to be thread-safe. /// + /// + /// 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 RelationalConventionSetBuilderDependencies() { } diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs index 8623ebb17de..9cb329b1c39 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs @@ -96,7 +96,7 @@ protected virtual void ProcessDbFunctionAdded( var methodInfo = dbFunctionBuilder.Metadata.MethodInfo; var dbFunctionAttribute = methodInfo.GetCustomAttributes().SingleOrDefault(); - dbFunctionBuilder.HasName(dbFunctionAttribute?.FunctionName ?? methodInfo.Name); + dbFunctionBuilder.HasName(dbFunctionAttribute?.Name ?? methodInfo.Name); dbFunctionBuilder.HasSchema(dbFunctionAttribute?.Schema); } } diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs index f2e24606e28..2a4f381e7d5 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs @@ -8,7 +8,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// A convention that configures the maximum object identifier length supported by the database. + /// A convention that configures the maximum object identifier length supported by the database. /// public class RelationalMaxIdentifierLengthConvention : IModelInitializedConvention { @@ -33,10 +33,7 @@ public RelationalMaxIdentifierLengthConvention( protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } /// - /// 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. + /// The maximum object identifier length supported by the database. /// public virtual int MaxIdentifierLength { get; } diff --git a/src/EFCore.Relational/Metadata/IConventionDbFunction.cs b/src/EFCore.Relational/Metadata/IConventionDbFunction.cs index 842ee0ced79..b198fc36087 100644 --- a/src/EFCore.Relational/Metadata/IConventionDbFunction.cs +++ b/src/EFCore.Relational/Metadata/IConventionDbFunction.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Metadata @@ -37,13 +37,13 @@ public interface IConventionDbFunction : IDbFunction /// /// The name of the function in the database. /// Indicates whether the configuration was specified using a data annotation. - void SetFunctionName([CanBeNull] string name, bool fromDataAnnotation = false); + void SetName([CanBeNull] string name, bool fromDataAnnotation = false); /// - /// Returns the configuration source for . + /// Returns the configuration source for . /// - /// The configuration source for . - ConfigurationSource? GetFunctionNameConfigurationSource(); + /// The configuration source for . + ConfigurationSource? GetNameConfigurationSource(); /// /// Sets the schema of the function in the database. diff --git a/src/EFCore.Relational/Metadata/IDbFunction.cs b/src/EFCore.Relational/Metadata/IDbFunction.cs index 67efc15e0ad..e509da8198a 100644 --- a/src/EFCore.Relational/Metadata/IDbFunction.cs +++ b/src/EFCore.Relational/Metadata/IDbFunction.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Metadata @@ -17,7 +17,7 @@ public interface IDbFunction /// /// The name of the function in the database. /// - string FunctionName { get; } + string Name { get; } /// /// The schema of the function in the database. diff --git a/src/EFCore.Relational/Metadata/IMutableDbFunction.cs b/src/EFCore.Relational/Metadata/IMutableDbFunction.cs index 9c16c624e49..2d24a3aa864 100644 --- a/src/EFCore.Relational/Metadata/IMutableDbFunction.cs +++ b/src/EFCore.Relational/Metadata/IMutableDbFunction.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Metadata @@ -18,7 +18,7 @@ public interface IMutableDbFunction : IDbFunction /// /// The name of the function in the database. /// - new string FunctionName { get; [param: CanBeNull] set; } + new string Name { get; [param: CanBeNull] set; } /// /// The schema of the function in the database. diff --git a/src/EFCore.Relational/Metadata/Internal/DbFunction.cs b/src/EFCore.Relational/Metadata/Internal/DbFunction.cs index 01d5ad3ac56..0a169e3c446 100644 --- a/src/EFCore.Relational/Metadata/Internal/DbFunction.cs +++ b/src/EFCore.Relational/Metadata/Internal/DbFunction.cs @@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -28,13 +28,13 @@ public class DbFunction : IMutableDbFunction, IConventionDbFunction private readonly string _annotationName; private readonly List _parameters; private string _schema; - private string _functionName; + private string _name; private string _storeType; private RelationalTypeMapping _typeMapping; private Func, SqlExpression> _translation; private ConfigurationSource? _schemaConfigurationSource; - private ConfigurationSource? _functionNameConfigurationSource; + private ConfigurationSource? _nameConfigurationSource; private ConfigurationSource? _storeTypeConfigurationSource; private ConfigurationSource? _typeMappingConfigurationSource; private ConfigurationSource? _translationConfigurationSource; @@ -183,10 +183,10 @@ private void UpdateSchemaConfigurationSource(ConfigurationSource configurationSo /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual string FunctionName + public virtual string Name { - get => _functionName ?? MethodInfo.Name; - set => SetFunctionName(value, ConfigurationSource.Explicit); + get => _name ?? MethodInfo.Name; + set => SetName(value, ConfigurationSource.Explicit); } /// @@ -195,17 +195,17 @@ public virtual string FunctionName /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual void SetFunctionName([NotNull] string name, ConfigurationSource configurationSource) + public virtual void SetName([NotNull] string name, ConfigurationSource configurationSource) { Check.NotNull(name, nameof(name)); - _functionName = name; + _name = name; - UpdateFunctionNameConfigurationSource(configurationSource); + UpdateNameConfigurationSource(configurationSource); } - private void UpdateFunctionNameConfigurationSource(ConfigurationSource configurationSource) - => _functionNameConfigurationSource = configurationSource.Max(_functionNameConfigurationSource); + private void UpdateNameConfigurationSource(ConfigurationSource configurationSource) + => _nameConfigurationSource = configurationSource.Max(_nameConfigurationSource); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -213,7 +213,7 @@ private void UpdateFunctionNameConfigurationSource(ConfigurationSource configura /// 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 ConfigurationSource? GetFunctionNameConfigurationSource() => _functionNameConfigurationSource; + public virtual ConfigurationSource? GetNameConfigurationSource() => _nameConfigurationSource; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -387,8 +387,8 @@ public static DbFunction RemoveDbFunction( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - void IConventionDbFunction.SetFunctionName(string name, bool fromDataAnnotation) - => SetFunctionName(name, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); + void IConventionDbFunction.SetName(string name, bool fromDataAnnotation) + => SetName(name, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Migrations/HistoryRepositoryDependencies.cs b/src/EFCore.Relational/Migrations/HistoryRepositoryDependencies.cs index 7b697c34384..c00198d26b5 100644 --- a/src/EFCore.Relational/Migrations/HistoryRepositoryDependencies.cs +++ b/src/EFCore.Relational/Migrations/HistoryRepositoryDependencies.cs @@ -62,19 +62,13 @@ public sealed class HistoryRepositoryDependencies /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// /// - /// The database creator. - /// A command builder for building raw SQL commands. - /// The connection to the database. - /// Options for the current context instance. - /// The model differ. - /// The SQL generator for Migrations operations. - /// Helpers for generating update SQL. - /// The convention set to use when creating the model. - /// The type mapper. - /// Contains the currently in use. - /// The logger for model building events. - /// The command logger. [EntityFrameworkInternal] public HistoryRepositoryDependencies( [NotNull] IRelationalDatabaseCreator databaseCreator, diff --git a/src/EFCore.Relational/Migrations/MigrationsAnnotationProviderDependencies.cs b/src/EFCore.Relational/Migrations/MigrationsAnnotationProviderDependencies.cs index d2e1544a8c9..fec4e1ae5f2 100644 --- a/src/EFCore.Relational/Migrations/MigrationsAnnotationProviderDependencies.cs +++ b/src/EFCore.Relational/Migrations/MigrationsAnnotationProviderDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Migrations @@ -27,7 +28,14 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation must be thread-safe. /// This service cannot depend on services registered as . /// + /// + /// 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 sealed class MigrationsAnnotationProviderDependencies { /// @@ -42,8 +50,20 @@ public sealed class MigrationsAnnotationProviderDependencies /// 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. + /// + /// + /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public MigrationsAnnotationProviderDependencies() { } diff --git a/src/EFCore.Relational/Migrations/MigrationsSqlGeneratorDependencies.cs b/src/EFCore.Relational/Migrations/MigrationsSqlGeneratorDependencies.cs index 035d5a99510..1e5716e0eea 100644 --- a/src/EFCore.Relational/Migrations/MigrationsSqlGeneratorDependencies.cs +++ b/src/EFCore.Relational/Migrations/MigrationsSqlGeneratorDependencies.cs @@ -55,12 +55,6 @@ public sealed class MigrationsSqlGeneratorDependencies /// doing so can result in application failures when updating to a new Entity Framework Core release. /// /// - /// The command builder factory. - /// High level SQL generator. - /// Helpers for SQL generation. - /// The type mapper. - /// Contains the currently in use. - /// A logger. [EntityFrameworkInternal] public MigrationsSqlGeneratorDependencies( [NotNull] IRelationalCommandBuilderFactory commandBuilderFactory, diff --git a/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs b/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs index 7d090df6e80..c3cc5e9ffcf 100644 --- a/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using System.Diagnostics; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Update; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Migrations.Operations { diff --git a/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs b/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs index e9c5686c1e5..731cb612d36 100644 --- a/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using System.Diagnostics; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Update; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Migrations.Operations { diff --git a/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs b/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs index 009eb5d6341..5e4c8a7f04c 100644 --- a/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs @@ -5,10 +5,10 @@ using System.Diagnostics; using System.Linq; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Update; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Migrations.Operations { diff --git a/src/EFCore.Relational/Query/Pipeline/CollectionInitializingExpression.cs b/src/EFCore.Relational/Query/CollectionInitializingExpression.cs similarity index 83% rename from src/EFCore.Relational/Query/Pipeline/CollectionInitializingExpression.cs rename to src/EFCore.Relational/Query/CollectionInitializingExpression.cs index 950264789c9..6ff19948efe 100644 --- a/src/EFCore.Relational/Query/Pipeline/CollectionInitializingExpression.cs +++ b/src/EFCore.Relational/Query/CollectionInitializingExpression.cs @@ -4,10 +4,8 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class CollectionInitializingExpression : Expression, IPrintable { @@ -33,7 +31,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) : this; } - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.StringBuilder.AppendLine("InitializeCollection:"); using (expressionPrinter.StringBuilder.Indent()) @@ -56,10 +54,10 @@ public void Print(ExpressionPrinter expressionPrinter) public override ExpressionType NodeType => ExpressionType.Extension; - public int CollectionId { get; } - public Expression Parent { get; } - public Expression ParentIdentifier { get; } - public Expression OuterIdentifier { get; } - public INavigation Navigation { get; } + public virtual int CollectionId { get; } + public virtual Expression Parent { get; } + public virtual Expression ParentIdentifier { get; } + public virtual Expression OuterIdentifier { get; } + public virtual INavigation Navigation { get; } } } diff --git a/src/EFCore.Relational/Query/Pipeline/CollectionPopulatingExpression.cs b/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs similarity index 75% rename from src/EFCore.Relational/Query/Pipeline/CollectionPopulatingExpression.cs rename to src/EFCore.Relational/Query/CollectionPopulatingExpression.cs index c7d41bd99df..7a3e7826c13 100644 --- a/src/EFCore.Relational/Query/Pipeline/CollectionPopulatingExpression.cs +++ b/src/EFCore.Relational/Query/CollectionPopulatingExpression.cs @@ -3,10 +3,8 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class CollectionPopulatingExpression : Expression, IPrintable { @@ -14,7 +12,7 @@ public CollectionPopulatingExpression(RelationalCollectionShaperExpression paren { Parent = parent; Type = type; - Include = include; + IsInclude = include; } protected override Expression VisitChildren(ExpressionVisitor visitor) @@ -22,11 +20,11 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) var parent = (RelationalCollectionShaperExpression)visitor.Visit(Parent); return parent != Parent - ? new CollectionPopulatingExpression(parent, Type, Include) + ? new CollectionPopulatingExpression(parent, Type, IsInclude) : this; } - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.StringBuilder.AppendLine("PopulateCollection:"); using (expressionPrinter.StringBuilder.Indent()) @@ -39,7 +37,7 @@ public void Print(ExpressionPrinter expressionPrinter) public override Type Type { get; } public override ExpressionType NodeType => ExpressionType.Extension; - public RelationalCollectionShaperExpression Parent { get; } - public bool Include { get; } + public virtual RelationalCollectionShaperExpression Parent { get; } + public virtual bool IsInclude { get; } } } diff --git a/src/EFCore.Relational/Query/Pipeline/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs similarity index 88% rename from src/EFCore.Relational/Query/Pipeline/EntityProjectionExpression.cs rename to src/EFCore.Relational/Query/EntityProjectionExpression.cs index a61337da021..4e9d6bc5186 100644 --- a/src/EFCore.Relational/Query/Pipeline/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -5,10 +5,9 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class EntityProjectionExpression : Expression { @@ -59,7 +58,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) : this; } - public EntityProjectionExpression MakeNullable() + public virtual EntityProjectionExpression MakeNullable() { if (_innerTable != null) { @@ -75,7 +74,7 @@ public EntityProjectionExpression MakeNullable() return new EntityProjectionExpression(EntityType, newCache); } - public EntityProjectionExpression UpdateEntityType(IEntityType derivedType) + public virtual EntityProjectionExpression UpdateEntityType(IEntityType derivedType) { if (_innerTable != null) { @@ -85,11 +84,11 @@ public EntityProjectionExpression UpdateEntityType(IEntityType derivedType) throw new InvalidOperationException("EntityProjectionExpression: Cannot update EntityType when _innerTable is null"); } - public IEntityType EntityType { get; } + public virtual IEntityType EntityType { get; } public override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => EntityType.ClrType; - public ColumnExpression BindProperty(IProperty property) + public virtual ColumnExpression BindProperty(IProperty property) { if (!EntityType.IsAssignableFrom(property.DeclaringEntityType) && !property.DeclaringEntityType.IsAssignableFrom(EntityType)) @@ -107,7 +106,7 @@ public ColumnExpression BindProperty(IProperty property) return expression; } - public void AddNavigationBinding(INavigation navigation, EntityShaperExpression entityShaper) + public virtual void AddNavigationBinding(INavigation navigation, EntityShaperExpression entityShaper) { if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) @@ -120,7 +119,7 @@ public void AddNavigationBinding(INavigation navigation, EntityShaperExpression _navigationExpressionsCache[navigation] = entityShaper; } - public EntityShaperExpression BindNavigation(INavigation navigation) + public virtual EntityShaperExpression BindNavigation(INavigation navigation) { if (!EntityType.IsAssignableFrom(navigation.DeclaringEntityType) && !navigation.DeclaringEntityType.IsAssignableFrom(EntityType)) diff --git a/src/EFCore.Relational/Query/Pipeline/ExpressionExtensions.cs b/src/EFCore.Relational/Query/ExpressionExtensions.cs similarity index 64% rename from src/EFCore.Relational/Query/Pipeline/ExpressionExtensions.cs rename to src/EFCore.Relational/Query/ExpressionExtensions.cs index 74d55c652b2..2ff11d320c5 100644 --- a/src/EFCore.Relational/Query/Pipeline/ExpressionExtensions.cs +++ b/src/EFCore.Relational/Query/ExpressionExtensions.cs @@ -1,20 +1,19 @@ // 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.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public static class ExpressionExtensions { - public static RelationalTypeMapping InferTypeMapping(params Expression[] expressions) + public static RelationalTypeMapping InferTypeMapping(params SqlExpression[] expressions) { for (var i = 0; i < expressions.Length; i++) { - if (expressions[i] is SqlExpression sql - && sql.TypeMapping != null) + var sql = expressions[i]; + if (sql.TypeMapping != null) { return sql.TypeMapping; } diff --git a/src/EFCore.Relational/Query/Pipeline/IMemberTranslator.cs b/src/EFCore.Relational/Query/IMemberTranslator.cs similarity index 71% rename from src/EFCore.Relational/Query/Pipeline/IMemberTranslator.cs rename to src/EFCore.Relational/Query/IMemberTranslator.cs index 22ba50cb0bb..473abd2aaed 100644 --- a/src/EFCore.Relational/Query/Pipeline/IMemberTranslator.cs +++ b/src/EFCore.Relational/Query/IMemberTranslator.cs @@ -3,9 +3,9 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IMemberTranslator { diff --git a/src/EFCore.Relational/Query/Pipeline/IMemberTranslatorPlugin.cs b/src/EFCore.Relational/Query/IMemberTranslatorPlugin.cs similarity index 93% rename from src/EFCore.Relational/Query/Pipeline/IMemberTranslatorPlugin.cs rename to src/EFCore.Relational/Query/IMemberTranslatorPlugin.cs index 1e8ec5d1385..1acb109b0b0 100644 --- a/src/EFCore.Relational/Query/Pipeline/IMemberTranslatorPlugin.cs +++ b/src/EFCore.Relational/Query/IMemberTranslatorPlugin.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { /// /// diff --git a/src/EFCore.Relational/Query/Pipeline/IMemberTranslatorProvider.cs b/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs similarity index 71% rename from src/EFCore.Relational/Query/Pipeline/IMemberTranslatorProvider.cs rename to src/EFCore.Relational/Query/IMemberTranslatorProvider.cs index 14d95b00f35..820fc349417 100644 --- a/src/EFCore.Relational/Query/Pipeline/IMemberTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/IMemberTranslatorProvider.cs @@ -3,9 +3,9 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IMemberTranslatorProvider { diff --git a/src/EFCore.Relational/Query/Pipeline/IMethodCallTranslator.cs b/src/EFCore.Relational/Query/IMethodCallTranslator.cs similarity index 73% rename from src/EFCore.Relational/Query/Pipeline/IMethodCallTranslator.cs rename to src/EFCore.Relational/Query/IMethodCallTranslator.cs index fe0739c0bd5..1301fb46f8b 100644 --- a/src/EFCore.Relational/Query/Pipeline/IMethodCallTranslator.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslator.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IMethodCallTranslator { diff --git a/src/EFCore.Relational/Query/Pipeline/IMethodCallTranslatorPlugin.cs b/src/EFCore.Relational/Query/IMethodCallTranslatorPlugin.cs similarity index 94% rename from src/EFCore.Relational/Query/Pipeline/IMethodCallTranslatorPlugin.cs rename to src/EFCore.Relational/Query/IMethodCallTranslatorPlugin.cs index 4f51aaedeb8..03762e812b7 100644 --- a/src/EFCore.Relational/Query/Pipeline/IMethodCallTranslatorPlugin.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslatorPlugin.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { /// /// diff --git a/src/EFCore.Relational/Query/Pipeline/IMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs similarity index 76% rename from src/EFCore.Relational/Query/Pipeline/IMethodCallTranslatorProvider.cs rename to src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs index 99cae2d894b..96ad71a1f97 100644 --- a/src/EFCore.Relational/Query/Pipeline/IMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/IMethodCallTranslatorProvider.cs @@ -4,9 +4,9 @@ using System.Collections.Generic; using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IMethodCallTranslatorProvider { diff --git a/src/EFCore.Relational/Query/Pipeline/IQuerySqlGeneratorFactory.cs b/src/EFCore.Relational/Query/IQuerySqlGeneratorFactory.cs similarity index 80% rename from src/EFCore.Relational/Query/Pipeline/IQuerySqlGeneratorFactory.cs rename to src/EFCore.Relational/Query/IQuerySqlGeneratorFactory.cs index 9831f288f40..16280262a6e 100644 --- a/src/EFCore.Relational/Query/Pipeline/IQuerySqlGeneratorFactory.cs +++ b/src/EFCore.Relational/Query/IQuerySqlGeneratorFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IQuerySqlGeneratorFactory { diff --git a/src/EFCore.Relational/Query/Pipeline/IRelationalSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs similarity index 80% rename from src/EFCore.Relational/Query/Pipeline/IRelationalSqlTranslatingExpressionVisitorFactory.cs rename to src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs index dd6a5a34930..f5161283270 100644 --- a/src/EFCore.Relational/Query/Pipeline/IRelationalSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/IRelationalSqlTranslatingExpressionVisitorFactory.cs @@ -2,9 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IRelationalSqlTranslatingExpressionVisitorFactory { diff --git a/src/EFCore.Relational/Query/Pipeline/ISqlExpressionFactory.cs b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs similarity index 80% rename from src/EFCore.Relational/Query/Pipeline/ISqlExpressionFactory.cs rename to src/EFCore.Relational/Query/ISqlExpressionFactory.cs index 562126421c7..141a3725027 100644 --- a/src/EFCore.Relational/Query/Pipeline/ISqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface ISqlExpressionFactory { @@ -17,6 +17,7 @@ public interface ISqlExpressionFactory RelationalTypeMapping GetTypeMappingForValue(object value); RelationalTypeMapping FindMapping(Type type); + SqlUnaryExpression MakeUnary(ExpressionType operatorType, SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null); SqlBinaryExpression MakeBinary(ExpressionType operatorType, SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping); // Comparison SqlBinaryExpression Equal(SqlExpression left, SqlExpression right); @@ -50,17 +51,17 @@ public interface ISqlExpressionFactory CaseExpression Case(IReadOnlyList whenClauses, SqlExpression elseResult); SqlFunctionExpression Function( - string functionName, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); + string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - string schema, string functionName, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); + string schema, string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - SqlExpression instance, string functionName, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); + SqlExpression instance, string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - string functionName, Type returnType, RelationalTypeMapping typeMapping = null); + string name, Type returnType, RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - string schema, string functionName, Type returnType, RelationalTypeMapping typeMapping = null); + string schema, string name, Type returnType, RelationalTypeMapping typeMapping = null); SqlFunctionExpression Function( - SqlExpression instance, string functionName, Type returnType, RelationalTypeMapping typeMapping = null); + SqlExpression instance, string name, Type returnType, RelationalTypeMapping typeMapping = null); ExistsExpression Exists(SelectExpression subquery, bool negated); InExpression In(SqlExpression item, SqlExpression values, bool negated); diff --git a/src/EFCore.Relational/Query/Pipeline/AsyncQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/AsyncQueryingEnumerable.cs similarity index 97% rename from src/EFCore.Relational/Query/Pipeline/AsyncQueryingEnumerable.cs rename to src/EFCore.Relational/Query/Internal/AsyncQueryingEnumerable.cs index d922c0ee100..349dc7f743d 100644 --- a/src/EFCore.Relational/Query/Pipeline/AsyncQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/AsyncQueryingEnumerable.cs @@ -8,12 +8,10 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitors.cs b/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs similarity index 55% rename from src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitors.cs rename to src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs index d1c6547448a..31d16f0e4b3 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitors.cs +++ b/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs @@ -2,44 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { - public class RelationalShapedQueryOptimizer : ShapedQueryOptimizer - { - public RelationalShapedQueryOptimizer( - QueryCompilationContext queryCompilationContext, - ISqlExpressionFactory sqlExpressionFactory) - { - UseRelationalNulls = RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).UseRelationalNulls; - SqlExpressionFactory = sqlExpressionFactory; - } - - protected ISqlExpressionFactory SqlExpressionFactory { get; } - protected bool UseRelationalNulls { get; } - - public override Expression Visit(Expression query) - { - query = base.Visit(query); - query = new SelectExpressionProjectionApplyingExpressionVisitor().Visit(query); - query = new CollectionJoinApplyingExpressionVisitor().Visit(query); - query = new SelectExpressionTableAliasUniquifyingExpressionVisitor().Visit(query); - - if (!UseRelationalNulls) - { - query = new NullSemanticsRewritingVisitor(SqlExpressionFactory).Visit(query); - } - - query = new SqlExpressionOptimizingVisitor(SqlExpressionFactory, UseRelationalNulls).Visit(query); - query = new NullComparisonTransformingExpressionVisitor().Visit(query); - - return query; - } - } - public class CollectionJoinApplyingExpressionVisitor : ExpressionVisitor { private int _collectionId; diff --git a/src/EFCore.Relational/Query/Pipeline/ComparisonTranslator.cs b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs similarity index 89% rename from src/EFCore.Relational/Query/Pipeline/ComparisonTranslator.cs rename to src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs index 7de02c7acea..c20e44eb49c 100644 --- a/src/EFCore.Relational/Query/Pipeline/ComparisonTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ComparisonTranslator.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class ComparisonTranslator : IMethodCallTranslator { @@ -17,7 +17,7 @@ public ComparisonTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (method.ReturnType == typeof(int)) { diff --git a/src/EFCore.Relational/Query/Pipeline/ContainsTranslator.cs b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs similarity index 84% rename from src/EFCore.Relational/Query/Pipeline/ContainsTranslator.cs rename to src/EFCore.Relational/Query/Internal/ContainsTranslator.cs index adc7d12b67a..9532de5de35 100644 --- a/src/EFCore.Relational/Query/Pipeline/ContainsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/ContainsTranslator.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class ContainsTranslator : IMethodCallTranslator { @@ -23,7 +23,7 @@ public ContainsTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (method.IsGenericMethod && method.GetGenericMethodDefinition().Equals(_containsMethod)) diff --git a/src/EFCore.Relational/Query/Pipeline/EnumHasFlagTranslator.cs b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs similarity index 82% rename from src/EFCore.Relational/Query/Pipeline/EnumHasFlagTranslator.cs rename to src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs index ba08751dca7..d76a8af23b6 100644 --- a/src/EFCore.Relational/Query/Pipeline/EnumHasFlagTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EnumHasFlagTranslator.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class EnumHasFlagTranslator : IMethodCallTranslator { @@ -20,7 +20,7 @@ public EnumHasFlagTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _methodInfo)) { diff --git a/src/EFCore.Relational/Query/Pipeline/EqualsTranslator.cs b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs similarity index 88% rename from src/EFCore.Relational/Query/Pipeline/EqualsTranslator.cs rename to src/EFCore.Relational/Query/Internal/EqualsTranslator.cs index ff1cde99714..130a4753d13 100644 --- a/src/EFCore.Relational/Query/Pipeline/EqualsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class EqualsTranslator : IMethodCallTranslator { @@ -18,7 +18,7 @@ public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { SqlExpression left = null; SqlExpression right = null; diff --git a/src/EFCore.Relational/Query/Pipeline/FromSqlParameterApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/FromSqlParameterApplyingExpressionVisitor.cs similarity index 96% rename from src/EFCore.Relational/Query/Pipeline/FromSqlParameterApplyingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/FromSqlParameterApplyingExpressionVisitor.cs index e8add377834..2a651205d30 100644 --- a/src/EFCore.Relational/Query/Pipeline/FromSqlParameterApplyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlParameterApplyingExpressionVisitor.cs @@ -6,11 +6,11 @@ using System.Data.Common; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/GetValueOrDefaultTranslator.cs b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs similarity index 86% rename from src/EFCore.Relational/Query/Pipeline/GetValueOrDefaultTranslator.cs rename to src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs index 08d4cb68677..1b5b094061b 100644 --- a/src/EFCore.Relational/Query/Pipeline/GetValueOrDefaultTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/GetValueOrDefaultTranslator.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class GetValueOrDefaultTranslator : IMethodCallTranslator { @@ -17,7 +17,7 @@ public GetValueOrDefaultTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (method.Name == nameof(Nullable.GetValueOrDefault) && method.ReturnType.IsNumeric()) diff --git a/src/EFCore.Relational/Query/Pipeline/InExpressionValuesExpandingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/InExpressionValuesExpandingExpressionVisitor.cs similarity index 93% rename from src/EFCore.Relational/Query/Pipeline/InExpressionValuesExpandingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/InExpressionValuesExpandingExpressionVisitor.cs index 545ffda4c4d..1d1d5258c0a 100644 --- a/src/EFCore.Relational/Query/Pipeline/InExpressionValuesExpandingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/InExpressionValuesExpandingExpressionVisitor.cs @@ -4,10 +4,10 @@ using System.Collections; using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor { @@ -73,25 +73,25 @@ public override Expression Visit(Expression expression) ? _sqlExpressionFactory.In( (SqlExpression)Visit(inExpression.Item), _sqlExpressionFactory.Constant(inValues, typeMapping), - inExpression.Negated) + inExpression.IsNegated) : null; var nullCheckExpression = hasNullValue - ? inExpression.Negated + ? inExpression.IsNegated ? _sqlExpressionFactory.IsNotNull(inExpression.Item) : _sqlExpressionFactory.IsNull(inExpression.Item) : null; if (updatedInExpression != null && nullCheckExpression != null) { - return inExpression.Negated + return inExpression.IsNegated ? _sqlExpressionFactory.AndAlso(updatedInExpression, nullCheckExpression) : _sqlExpressionFactory.OrElse(updatedInExpression, nullCheckExpression); } if (updatedInExpression == null && nullCheckExpression == null) { - return _sqlExpressionFactory.Equal(_sqlExpressionFactory.Constant(true), _sqlExpressionFactory.Constant(inExpression.Negated)); + return _sqlExpressionFactory.Equal(_sqlExpressionFactory.Constant(true), _sqlExpressionFactory.Constant(inExpression.IsNegated)); } return (SqlExpression)updatedInExpression ?? nullCheckExpression; diff --git a/src/EFCore.Relational/Query/Pipeline/IncludeCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/IncludeCompilingExpressionVisitor.cs similarity index 98% rename from src/EFCore.Relational/Query/Pipeline/IncludeCompilingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/IncludeCompilingExpressionVisitor.cs index 99b11737820..cc45e1abeeb 100644 --- a/src/EFCore.Relational/Query/Pipeline/IncludeCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/IncludeCompilingExpressionVisitor.cs @@ -13,11 +13,9 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor { @@ -376,7 +374,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var collectionShaper = collectionPopulatingExpression.Parent; var relatedEntityClrType = ((LambdaExpression)collectionShaper.InnerShaper).ReturnType; - if (collectionPopulatingExpression.Include) + if (collectionPopulatingExpression.IsInclude) { var entityClrType = collectionShaper.Navigation.DeclaringEntityType.ClrType; var inverseNavigation = collectionShaper.Navigation.FindInverse(); diff --git a/src/EFCore.Relational/Query/Pipeline/IsNullOrEmptyTranslator.cs b/src/EFCore.Relational/Query/Internal/IsNullOrEmptyTranslator.cs similarity index 85% rename from src/EFCore.Relational/Query/Pipeline/IsNullOrEmptyTranslator.cs rename to src/EFCore.Relational/Query/Internal/IsNullOrEmptyTranslator.cs index c9051a6570b..f9d60b1bf81 100644 --- a/src/EFCore.Relational/Query/Pipeline/IsNullOrEmptyTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/IsNullOrEmptyTranslator.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class StringMethodTranslator : IMethodCallTranslator { @@ -22,7 +22,7 @@ public StringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _isNullOrEmptyMethodInfo)) { diff --git a/src/EFCore.Relational/Query/Pipeline/LikeTranslator.cs b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs similarity index 84% rename from src/EFCore.Relational/Query/Pipeline/LikeTranslator.cs rename to src/EFCore.Relational/Query/Internal/LikeTranslator.cs index dd58ebe283d..5fa8a4f9c35 100644 --- a/src/EFCore.Relational/Query/Pipeline/LikeTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/LikeTranslator.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class LikeTranslator : IMethodCallTranslator { @@ -26,7 +26,7 @@ public LikeTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _methodInfo)) { diff --git a/src/EFCore.Relational/Query/Pipeline/NullComparisonTransformingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/NullComparisonTransformingExpressionVisitor.cs similarity index 90% rename from src/EFCore.Relational/Query/Pipeline/NullComparisonTransformingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/NullComparisonTransformingExpressionVisitor.cs index 82f2b0753dd..35c1077a300 100644 --- a/src/EFCore.Relational/Query/Pipeline/NullComparisonTransformingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/NullComparisonTransformingExpressionVisitor.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class NullComparisonTransformingExpressionVisitor : ExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/NullSemanticsRewritingVisitor.cs b/src/EFCore.Relational/Query/Internal/NullSemanticsRewritingVisitor.cs similarity index 98% rename from src/EFCore.Relational/Query/Pipeline/NullSemanticsRewritingVisitor.cs rename to src/EFCore.Relational/Query/Internal/NullSemanticsRewritingVisitor.cs index 408a0e3ebf1..dbb58746265 100644 --- a/src/EFCore.Relational/Query/Pipeline/NullSemanticsRewritingVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/NullSemanticsRewritingVisitor.cs @@ -4,10 +4,9 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class NullSemanticsRewritingVisitor : ExpressionVisitor { @@ -54,7 +53,7 @@ protected override Expression VisitExtension(Expression extensionExpression) case LeftJoinExpression leftJoinExpression: return VisitLeftJoinExpression(leftJoinExpression); - case SubSelectExpression subSelectExpression: + case ScalarSubqueryExpression subSelectExpression: var result = base.VisitExtension(subSelectExpression); _isNullable = true; @@ -74,7 +73,7 @@ private SqlConstantExpression VisitSqlConstantExpression(SqlConstantExpression s private ColumnExpression VisitColumnExpression(ColumnExpression columnExpression) { - _isNullable = columnExpression.Nullable; + _isNullable = columnExpression.IsNullable; return columnExpression; } diff --git a/src/EFCore.Relational/Query/Pipeline/NullableValueTranslator.cs b/src/EFCore.Relational/Query/Internal/NullableValueTranslator.cs similarity index 79% rename from src/EFCore.Relational/Query/Pipeline/NullableValueTranslator.cs rename to src/EFCore.Relational/Query/Internal/NullableValueTranslator.cs index 3d32b40ff80..2aa9a5ceb1f 100644 --- a/src/EFCore.Relational/Query/Pipeline/NullableValueTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/NullableValueTranslator.cs @@ -3,9 +3,9 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class NullableMemberTranslator : IMemberTranslator { @@ -16,7 +16,7 @@ public NullableMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (member.DeclaringType.IsNullableType()) { diff --git a/src/EFCore.Relational/Query/Pipeline/ParameterValueBasedSelectExpressionOptimizer.cs b/src/EFCore.Relational/Query/Internal/ParameterValueBasedSelectExpressionOptimizer.cs similarity index 91% rename from src/EFCore.Relational/Query/Pipeline/ParameterValueBasedSelectExpressionOptimizer.cs rename to src/EFCore.Relational/Query/Internal/ParameterValueBasedSelectExpressionOptimizer.cs index d967ff62f78..c734ffce4d5 100644 --- a/src/EFCore.Relational/Query/Pipeline/ParameterValueBasedSelectExpressionOptimizer.cs +++ b/src/EFCore.Relational/Query/Internal/ParameterValueBasedSelectExpressionOptimizer.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/QuerySqlGeneratorFactory.cs b/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs similarity index 93% rename from src/EFCore.Relational/Query/Pipeline/QuerySqlGeneratorFactory.cs rename to src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs index 6a98de8d683..0f9d5743cd4 100644 --- a/src/EFCore.Relational/Query/Pipeline/QuerySqlGeneratorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/QuerySqlGeneratorFactory.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class QuerySqlGeneratorFactory : IQuerySqlGeneratorFactory { diff --git a/src/EFCore.Relational/Query/Pipeline/QueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs similarity index 98% rename from src/EFCore.Relational/Query/Pipeline/QueryingEnumerable.cs rename to src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs index e6093f20fce..e06ad0aedda 100644 --- a/src/EFCore.Relational/Query/Pipeline/QueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/QueryingEnumerable.cs @@ -8,10 +8,10 @@ using System.Linq; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs similarity index 95% rename from src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs index 3e4eea11607..21d6b006ba2 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs @@ -6,13 +6,11 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class RelationalProjectionBindingExpressionVisitor : ExpressionVisitor { @@ -33,7 +31,7 @@ public RelationalProjectionBindingExpressionVisitor( _sqlTranslator = sqlTranslatingExpressionVisitor; } - public Expression Translate(SelectExpression selectExpression, Expression expression) + public virtual Expression Translate(SelectExpression selectExpression, Expression expression) { _selectExpression = selectExpression; _clientEval = false; @@ -115,7 +113,7 @@ public override Expression Visit(Expression expression) if (subquery != null) { - if (subquery.ResultType == ResultType.Enumerable) + if (subquery.ResultCardinality == ResultCardinality.Enumerable) { return _selectExpression.AddCollectionProjection(subquery, null, subquery.ShaperExpression.Type); } @@ -218,7 +216,7 @@ protected override Expression VisitNew(NewExpression newExpression) } else { - var projectionMember = _projectionMembers.Peek().AddMember(newExpression.Members[i]); + var projectionMember = _projectionMembers.Peek().Append(newExpression.Members[i]); _projectionMembers.Push(projectionMember); newArguments[i] = Visit(newExpression.Arguments[i]); if (newArguments[i] == null) @@ -250,7 +248,7 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp } else { - var projectionMember = _projectionMembers.Peek().AddMember(memberAssignment.Member); + var projectionMember = _projectionMembers.Peek().Append(memberAssignment.Member); _projectionMembers.Push(projectionMember); var visitedExpression = Visit(memberAssignment.Expression); diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs similarity index 86% rename from src/EFCore.Relational/Query/Pipeline/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs rename to src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs index 07c6341b969..c0eba591b5c 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -2,9 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class RelationalQueryableMethodTranslatingExpressionVisitorFactory : IQueryableMethodTranslatingExpressionVisitorFactory { @@ -19,7 +18,7 @@ public RelationalQueryableMethodTranslatingExpressionVisitorFactory( _relationalSqlTranslatingExpressionVisitorFactory = relationalSqlTranslatingExpressionVisitorFactory; } - public QueryableMethodTranslatingExpressionVisitor Create(IModel model) + public virtual QueryableMethodTranslatingExpressionVisitor Create(IModel model) { return new RelationalQueryableMethodTranslatingExpressionVisitor( model, diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryExpressionVisitorFactory.cs similarity index 83% rename from src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryExpressionVisitorFactory.cs rename to src/EFCore.Relational/Query/Internal/RelationalShapedQueryExpressionVisitorFactory.cs index 7b828473d02..b8a8a2f0da6 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryExpressionVisitorFactory.cs @@ -1,12 +1,9 @@ // 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.Metadata; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class RelationalShapedQueryCompilingExpressionVisitorFactory : IShapedQueryCompilingExpressionVisitorFactory { @@ -27,7 +24,7 @@ public RelationalShapedQueryCompilingExpressionVisitorFactory( _parameterNameGeneratorFactory = parameterNameGeneratorFactory; } - public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) + public virtual ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) { return new RelationalShapedQueryCompilingExpressionVisitor( queryCompilationContext, diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitorsFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryOptimizingExpressionVisitorsFactory.cs similarity index 55% rename from src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitorsFactory.cs rename to src/EFCore.Relational/Query/Internal/RelationalShapedQueryOptimizingExpressionVisitorsFactory.cs index cd0f3f4c56b..096ab687ca6 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitorsFactory.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalShapedQueryOptimizingExpressionVisitorsFactory.cs @@ -1,20 +1,19 @@ // 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.Query.Pipeline; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { - public class RelationalShapedQueryOptimizerFactory : ShapedQueryOptimizerFactory + public class RelationalShapedQueryOptimizerFactory : IShapedQueryOptimizerFactory { - protected ISqlExpressionFactory SqlExpressionFactory { get; private set; } + protected virtual ISqlExpressionFactory SqlExpressionFactory { get; private set; } public RelationalShapedQueryOptimizerFactory(ISqlExpressionFactory sqlExpressionFactory) { SqlExpressionFactory = sqlExpressionFactory; } - public override ShapedQueryOptimizer Create(QueryCompilationContext queryCompilationContext) + public virtual ShapedQueryOptimizer Create(QueryCompilationContext queryCompilationContext) { return new RelationalShapedQueryOptimizer(queryCompilationContext, SqlExpressionFactory); } diff --git a/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs new file mode 100644 index 00000000000..e36b2994c12 --- /dev/null +++ b/src/EFCore.Relational/Query/Internal/RelationalSqlTranslatingExpressionVisitorFactory.cs @@ -0,0 +1,137 @@ +// 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.Collections.Generic; +using JetBrains.Annotations; +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 a single instance + /// is used by many instances. The implementation must be thread-safe. + /// This service cannot depend on services registered as . + /// + /// + public sealed class RelationalSqlTranslatingExpressionVisitorFactoryDependencies + { + /// + /// + /// 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 RelationalSqlTranslatingExpressionVisitorFactoryDependencies( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IMemberTranslatorProvider memberTranslatorProvider, + [NotNull] IMethodCallTranslatorProvider methodCallTranslatorProvider) + { + Check.NotNull(sqlExpressionFactory, nameof(sqlExpressionFactory)); + Check.NotNull(memberTranslatorProvider, nameof(memberTranslatorProvider)); + Check.NotNull(methodCallTranslatorProvider, nameof(methodCallTranslatorProvider)); + + SqlExpressionFactory = sqlExpressionFactory; + MemberTranslatorProvider = memberTranslatorProvider; + MethodCallTranslatorProvider = methodCallTranslatorProvider; + } + + /// + /// The expression factory.. + /// + public ISqlExpressionFactory SqlExpressionFactory { get; } + + /// + /// The member translation provider. + /// + public IMemberTranslatorProvider MemberTranslatorProvider { get; } + + /// + /// The method-call translation provider. + /// + public IMethodCallTranslatorProvider MethodCallTranslatorProvider { 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 RelationalSqlTranslatingExpressionVisitorFactoryDependencies With([NotNull] ISqlExpressionFactory sqlExpressionFactory) + => new RelationalSqlTranslatingExpressionVisitorFactoryDependencies(sqlExpressionFactory, MemberTranslatorProvider, MethodCallTranslatorProvider); + + /// + /// 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 RelationalSqlTranslatingExpressionVisitorFactoryDependencies With([NotNull] IMemberTranslatorProvider memberTranslatorProvider) + => new RelationalSqlTranslatingExpressionVisitorFactoryDependencies(SqlExpressionFactory, memberTranslatorProvider, MethodCallTranslatorProvider); + + /// + /// 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 RelationalSqlTranslatingExpressionVisitorFactoryDependencies With([NotNull] IMethodCallTranslatorProvider methodCallTranslatorProvider) + => new RelationalSqlTranslatingExpressionVisitorFactoryDependencies(SqlExpressionFactory, MemberTranslatorProvider, methodCallTranslatorProvider); + } + + public class RelationalSqlTranslatingExpressionVisitorFactory : IRelationalSqlTranslatingExpressionVisitorFactory + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + private readonly IMemberTranslatorProvider _memberTranslatorProvider; + private readonly IMethodCallTranslatorProvider _methodCallTranslatorProvider; + + public RelationalSqlTranslatingExpressionVisitorFactory( + [NotNull] RelationalSqlTranslatingExpressionVisitorFactoryDependencies dependencies) + { + _sqlExpressionFactory = dependencies.SqlExpressionFactory; + _memberTranslatorProvider = dependencies.MemberTranslatorProvider; + _methodCallTranslatorProvider = dependencies.MethodCallTranslatorProvider; + } + + public virtual RelationalSqlTranslatingExpressionVisitor Create( + IModel model, + QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) + { + return new RelationalSqlTranslatingExpressionVisitor( + model, + queryableMethodTranslatingExpressionVisitor, + _sqlExpressionFactory, + _memberTranslatorProvider, + _methodCallTranslatorProvider); + } + } +} diff --git a/src/EFCore.Relational/Query/Pipeline/SelectExpressionProjectionApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs similarity index 80% rename from src/EFCore.Relational/Query/Pipeline/SelectExpressionProjectionApplyingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs index c1732161ccc..53b64a8c01a 100644 --- a/src/EFCore.Relational/Query/Pipeline/SelectExpressionProjectionApplyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class SelectExpressionProjectionApplyingExpressionVisitor : ExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/SelectExpressionTableAliasUniquifyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SelectExpressionTableAliasUniquifyingExpressionVisitor.cs similarity index 92% rename from src/EFCore.Relational/Query/Pipeline/SelectExpressionTableAliasUniquifyingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/SelectExpressionTableAliasUniquifyingExpressionVisitor.cs index 0d838187ed9..a0652d55676 100644 --- a/src/EFCore.Relational/Query/Pipeline/SelectExpressionTableAliasUniquifyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SelectExpressionTableAliasUniquifyingExpressionVisitor.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class SelectExpressionTableAliasUniquifyingExpressionVisitor : ExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/ShaperExpressionDedupingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/ShaperExpressionDedupingExpressionVisitor.cs similarity index 96% rename from src/EFCore.Relational/Query/Pipeline/ShaperExpressionDedupingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/ShaperExpressionDedupingExpressionVisitor.cs index a2cea173327..6001b03791c 100644 --- a/src/EFCore.Relational/Query/Pipeline/ShaperExpressionDedupingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/ShaperExpressionDedupingExpressionVisitor.cs @@ -4,11 +4,10 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class ShaperExpressionProcessingExpressionVisitor : ExpressionVisitor { @@ -33,7 +32,7 @@ public ShaperExpressionProcessingExpressionVisitor( _indexMapParameter = indexMapParameter; } - public Expression Inject(Expression expression) + public virtual Expression Inject(Expression expression) { var result = Visit(expression); diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitorFactory.cs deleted file mode 100644 index 6f48951b6cc..00000000000 --- a/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitorFactory.cs +++ /dev/null @@ -1,37 +0,0 @@ -// 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.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; - -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline -{ - public class RelationalSqlTranslatingExpressionVisitorFactory : IRelationalSqlTranslatingExpressionVisitorFactory - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - private readonly IMemberTranslatorProvider _memberTranslatorProvider; - private readonly IMethodCallTranslatorProvider _methodCallTranslatorProvider; - - public RelationalSqlTranslatingExpressionVisitorFactory( - ISqlExpressionFactory sqlExpressionFactory, - IMemberTranslatorProvider memberTranslatorProvider, - IMethodCallTranslatorProvider methodCallTranslatorProvider) - { - _sqlExpressionFactory = sqlExpressionFactory; - _memberTranslatorProvider = memberTranslatorProvider; - _methodCallTranslatorProvider = methodCallTranslatorProvider; - } - - public virtual RelationalSqlTranslatingExpressionVisitor Create( - IModel model, - QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) - { - return new RelationalSqlTranslatingExpressionVisitor( - model, - queryableMethodTranslatingExpressionVisitor, - _sqlExpressionFactory, - _memberTranslatorProvider, - _methodCallTranslatorProvider); - } - } -} diff --git a/src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs similarity index 96% rename from src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs rename to src/EFCore.Relational/Query/QuerySqlGenerator.cs index e1b10b5419e..dd404b7417c 100644 --- a/src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -7,11 +7,11 @@ using System.IO; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class QuerySqlGenerator : SqlExpressionVisitor { @@ -174,11 +174,11 @@ protected virtual void GenerateSelect(SelectExpression selectExpression) GenerateList(selectExpression.GroupBy, e => Visit(e)); } - if (selectExpression.HavingExpression != null) + if (selectExpression.Having != null) { _relationalCommandBuilder.AppendLine().Append("HAVING "); - Visit(selectExpression.HavingExpression); + Visit(selectExpression.Having); } GenerateOrderings(selectExpression); @@ -256,7 +256,7 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction _relationalCommandBuilder.Append("."); } - _relationalCommandBuilder.Append(sqlFunctionExpression.FunctionName); + _relationalCommandBuilder.Append(sqlFunctionExpression.Name); } else { @@ -268,7 +268,7 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction } _relationalCommandBuilder - .Append(_sqlGenerationHelper.DelimitIdentifier(sqlFunctionExpression.FunctionName)); + .Append(_sqlGenerationHelper.DelimitIdentifier(sqlFunctionExpression.Name)); } if (!sqlFunctionExpression.IsNiladic) @@ -294,7 +294,7 @@ protected override Expression VisitColumn(ColumnExpression columnExpression) protected override Expression VisitTable(TableExpression tableExpression) { _relationalCommandBuilder - .Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Table, tableExpression.Schema)) + .Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Name, tableExpression.Schema)) .Append(AliasSeparator) .Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Alias)); @@ -444,7 +444,7 @@ protected override Expression VisitOrdering(OrderingExpression orderingExpressio Visit(orderingExpression.Expression); } - if (!orderingExpression.Ascending) + if (!orderingExpression.IsAscending) { _relationalCommandBuilder.Append(" DESC"); } @@ -568,7 +568,7 @@ protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpressio protected override Expression VisitExists(ExistsExpression existsExpression) { - if (existsExpression.Negated) + if (existsExpression.IsNegated) { _relationalCommandBuilder.Append("NOT "); } @@ -590,7 +590,7 @@ protected override Expression VisitIn(InExpression inExpression) if (inExpression.Values != null) { Visit(inExpression.Item); - _relationalCommandBuilder.Append(inExpression.Negated ? " NOT IN " : " IN "); + _relationalCommandBuilder.Append(inExpression.IsNegated ? " NOT IN " : " IN "); _relationalCommandBuilder.Append("("); var valuesConstant = (SqlConstantExpression)inExpression.Values; var valuesList = ((IEnumerable)valuesConstant.Value) @@ -601,7 +601,7 @@ protected override Expression VisitIn(InExpression inExpression) else { Visit(inExpression.Item); - _relationalCommandBuilder.Append(inExpression.Negated ? " NOT IN " : " IN "); + _relationalCommandBuilder.Append(inExpression.IsNegated ? " NOT IN " : " IN "); _relationalCommandBuilder.AppendLine("("); using (_relationalCommandBuilder.Indent()) @@ -729,17 +729,17 @@ protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpressio return leftJoinExpression; } - protected override Expression VisitSubSelect(SubSelectExpression subSelectExpression) + protected override Expression VisitSubSelect(ScalarSubqueryExpression scalarSubqueryExpression) { _relationalCommandBuilder.AppendLine("("); using (_relationalCommandBuilder.Indent()) { - Visit(subSelectExpression.Subquery); + Visit(scalarSubqueryExpression.Subquery); } _relationalCommandBuilder.Append(")"); - return subSelectExpression; + return scalarSubqueryExpression; } } } diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalCollectionShaperExpression.cs b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs similarity index 84% rename from src/EFCore.Relational/Query/Pipeline/RelationalCollectionShaperExpression.cs rename to src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs index de4f78ea9a3..2617d1f4787 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs @@ -5,10 +5,8 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class RelationalCollectionShaperExpression : Expression, IPrintable { @@ -30,13 +28,13 @@ public RelationalCollectionShaperExpression( ElementType = elementType; } - public int CollectionId { get; } - public Expression ParentIdentifier { get; } - public Expression OuterIdentifier { get; } - public Expression SelfIdentifier { get; } - public Expression InnerShaper { get; } - public INavigation Navigation { get; } - public Type ElementType { get; } + public virtual int CollectionId { get; } + public virtual Expression ParentIdentifier { get; } + public virtual Expression OuterIdentifier { get; } + public virtual Expression SelfIdentifier { get; } + public virtual Expression InnerShaper { get; } + public virtual INavigation Navigation { get; } + public virtual Type ElementType { get; } public override Type Type => Navigation?.ClrType ?? typeof(List<>).MakeGenericType(ElementType); public override ExpressionType NodeType => ExpressionType.Extension; @@ -51,7 +49,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(parentIdentifier, outerIdentifier, selfIdentifier, innerShaper); } - public RelationalCollectionShaperExpression Update( + public virtual RelationalCollectionShaperExpression Update( Expression parentIdentifier, Expression outerIdentifier, Expression selfIdentifier, Expression innerShaper) { return parentIdentifier != ParentIdentifier @@ -63,7 +61,7 @@ public RelationalCollectionShaperExpression Update( : this; } - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.StringBuilder.AppendLine("RelationalCollectionShaper:"); using (expressionPrinter.StringBuilder.Indent()) diff --git a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs index c924c0364ca..30fb8791247 100644 --- a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs +++ b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGeneratorDependencies.cs @@ -49,8 +49,14 @@ public sealed class RelationalCompiledQueryCacheKeyGeneratorDependencies /// 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. + /// /// - /// Options for the current instance. + [EntityFrameworkInternal] public RelationalCompiledQueryCacheKeyGeneratorDependencies([NotNull] IDbContextOptions contextOptions) { Check.NotNull(contextOptions, nameof(contextOptions)); diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalMemberTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs similarity index 64% rename from src/EFCore.Relational/Query/Pipeline/RelationalMemberTranslatorProvider.cs rename to src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs index 56fe401d2d7..3a79755e119 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalMemberTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMemberTranslatorProvider.cs @@ -5,28 +5,28 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class RelationalMemberTranslatorProvider : IMemberTranslatorProvider { private readonly List _plugins = new List(); private readonly List _translators = new List(); - public RelationalMemberTranslatorProvider(ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) + public RelationalMemberTranslatorProvider(RelationalMemberTranslatorProviderDependencies dependencies) { - _plugins.AddRange(plugins.SelectMany(p => p.Translators)); + _plugins.AddRange(dependencies.Plugins.SelectMany(p => p.Translators)); _translators .AddRange( new[] { - new NullableMemberTranslator(sqlExpressionFactory), + new NullableMemberTranslator(dependencies.SqlExpressionFactory), }); } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { return _plugins.Concat(_translators) .Select(t => t.Translate(instance, member, returnType)).FirstOrDefault(t => t != null); diff --git a/src/EFCore.Relational/Query/RelationalMemberTranslatorProviderDependencies.cs b/src/EFCore.Relational/Query/RelationalMemberTranslatorProviderDependencies.cs new file mode 100644 index 00000000000..9c38bdfad24 --- /dev/null +++ b/src/EFCore.Relational/Query/RelationalMemberTranslatorProviderDependencies.cs @@ -0,0 +1,93 @@ +// 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.Collections.Generic; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; +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 a single instance + /// is used by many instances. The implementation must be thread-safe. + /// This service cannot depend on services registered as . + /// + /// + public sealed class RelationalMemberTranslatorProviderDependencies + { + /// + /// + /// 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 RelationalMemberTranslatorProviderDependencies( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IEnumerable plugins) + { + Check.NotNull(sqlExpressionFactory, nameof(sqlExpressionFactory)); + Check.NotNull(plugins, nameof(plugins)); + + SqlExpressionFactory = sqlExpressionFactory; + Plugins = plugins; + } + + /// + /// The expression factory.. + /// + public ISqlExpressionFactory SqlExpressionFactory { get; } + + /// + /// Registered plugins. + /// + public IEnumerable Plugins { 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 RelationalMemberTranslatorProviderDependencies With([NotNull] ISqlExpressionFactory sqlExpressionFactory) + => new RelationalMemberTranslatorProviderDependencies(sqlExpressionFactory, Plugins); + + /// + /// 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 RelationalMemberTranslatorProviderDependencies With([NotNull] IEnumerable plugins) + => new RelationalMemberTranslatorProviderDependencies(SqlExpressionFactory, plugins); + } +} diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs similarity index 76% rename from src/EFCore.Relational/Query/Pipeline/RelationalMethodCallTranslatorProvider.cs rename to src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs index b06a2a3114a..17e51ca5da0 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs @@ -4,10 +4,12 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class RelationalMethodCallTranslatorProvider : IMethodCallTranslatorProvider { @@ -15,11 +17,11 @@ public class RelationalMethodCallTranslatorProvider : IMethodCallTranslatorProvi private readonly List _translators = new List(); private readonly ISqlExpressionFactory _sqlExpressionFactory; - public RelationalMethodCallTranslatorProvider( - ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) + public RelationalMethodCallTranslatorProvider([NotNull] RelationalMethodCallTranslatorProviderDependencies dependencies) { - _plugins.AddRange(plugins.SelectMany(p => p.Translators)); + _plugins.AddRange(dependencies.Plugins.SelectMany(p => p.Translators)); + + var sqlExpressionFactory = dependencies.SqlExpressionFactory; _translators.AddRange( new IMethodCallTranslator[] { @@ -34,7 +36,7 @@ public RelationalMethodCallTranslatorProvider( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo method, IList arguments) { var dbFunction = model.FindDbFunction(method); if (dbFunction != null) @@ -43,7 +45,7 @@ public SqlExpression Translate(IModel model, SqlExpression instance, MethodInfo arguments.Select(e => _sqlExpressionFactory.ApplyDefaultTypeMapping(e)).ToList()) ?? _sqlExpressionFactory.Function( dbFunction.Schema, - dbFunction.FunctionName, + dbFunction.Name, arguments, method.ReturnType); } diff --git a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProviderDependencies.cs b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProviderDependencies.cs new file mode 100644 index 00000000000..3eb7af4defe --- /dev/null +++ b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProviderDependencies.cs @@ -0,0 +1,93 @@ +// 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.Collections.Generic; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; +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 a single instance + /// is used by many instances. The implementation must be thread-safe. + /// This service cannot depend on services registered as . + /// + /// + public sealed class RelationalMethodCallTranslatorProviderDependencies + { + /// + /// + /// 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 RelationalMethodCallTranslatorProviderDependencies( + [NotNull] ISqlExpressionFactory sqlExpressionFactory, + [NotNull] IEnumerable plugins) + { + Check.NotNull(sqlExpressionFactory, nameof(sqlExpressionFactory)); + Check.NotNull(plugins, nameof(plugins)); + + SqlExpressionFactory = sqlExpressionFactory; + Plugins = plugins; + } + + /// + /// The expression factory.. + /// + public ISqlExpressionFactory SqlExpressionFactory { get; } + + /// + /// Registered plugins. + /// + public IEnumerable Plugins { 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 RelationalMethodCallTranslatorProviderDependencies With([NotNull] ISqlExpressionFactory sqlExpressionFactory) + => new RelationalMethodCallTranslatorProviderDependencies(sqlExpressionFactory, Plugins); + + /// + /// 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 RelationalMethodCallTranslatorProviderDependencies With([NotNull] IEnumerable plugins) + => new RelationalMethodCallTranslatorProviderDependencies(SqlExpressionFactory, plugins); + } +} diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalProjectionBindingRemovingExpressionVisitor.cs similarity index 97% rename from src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingRemovingExpressionVisitor.cs rename to src/EFCore.Relational/Query/RelationalProjectionBindingRemovingExpressionVisitor.cs index 7e34afeaf05..69b2f1300ab 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalProjectionBindingRemovingExpressionVisitor.cs @@ -10,11 +10,10 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor { @@ -118,7 +117,7 @@ private object GetProjectionIndex(ProjectionBindingExpression projectionBindingE } private static bool IsNullableProjection(ProjectionExpression projection) - => !(projection.Expression is ColumnExpression column) || column.Nullable; + => !(projection.Expression is ColumnExpression column) || column.IsNullable; private static Expression CreateGetValueExpression( Expression dbDataReader, @@ -201,8 +200,6 @@ Expression valueExpression return valueExpression; } - - } } } diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs similarity index 98% rename from src/EFCore.Relational/Query/Pipeline/RelationalQueryableMethodTranslatingExpressionVisitor.cs rename to src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 8f8adb6fd25..6eecbe45866 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -3,21 +3,19 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; -using System.Diagnostics; +using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class RelationalQueryableMethodTranslatingExpressionVisitor : QueryableMethodTranslatingExpressionVisitor { @@ -54,6 +52,9 @@ private RelationalQueryableMethodTranslatingExpressionVisitor( _sqlExpressionFactory = sqlExpressionFactory; } + private static Type CreateTransparentIdentifierType(Type outerType, Type innerType) + => typeof(TransparentIdentifier<,>).MakeGenericType(outerType, innerType); + protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.Method.DeclaringType == typeof(RelationalQueryableExtensions) @@ -308,10 +309,14 @@ protected override ShapedQueryExpression TranslateGroupBy( source.ShaperExpression, source.ShaperExpression.Type.GetTypeInfo().GetMember(nameof(IGrouping.Key))[0]); - var newResultSelectorBody = ReplacingExpressionVisitor.Replace( - resultSelector.Parameters[0], keyAccessExpression, - resultSelector.Parameters[1], source.ShaperExpression, - resultSelector.Body); + var original1 = resultSelector.Parameters[0]; + var original2 = resultSelector.Parameters[1]; + + var newResultSelectorBody = new ReplacingExpressionVisitor( + new Dictionary { + { original1, keyAccessExpression }, + { original2, source.ShaperExpression } + }).Visit(resultSelector.Body); source.ShaperExpression = _projectionBindingExpressionVisitor.Translate(selectExpression, newResultSelectorBody); @@ -907,7 +912,7 @@ public WeakEntityExpandingExpressionVisitor( _sqlExpressionFactory = sqlExpressionFactory; } - public Expression Expand(SelectExpression selectExpression, Expression lambdaBody) + public virtual Expression Expand(SelectExpression selectExpression, Expression lambdaBody) { _selectExpression = selectExpression; diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs similarity index 95% rename from src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs rename to src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs index 6a22c06f45d..db9eb8bed74 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -4,16 +4,13 @@ using System; using System.Collections.Generic; using System.Data.Common; -using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public partial class RelationalShapedQueryCompilingExpressionVisitor : ShapedQueryCompilingExpressionVisitor { @@ -61,7 +58,7 @@ protected override Expression VisitShapedQueryExpression(ShapedQueryExpression s shaper = new RelationalProjectionBindingRemovingExpressionVisitor(selectExpression, dataReaderParameter) .Visit(shaper); shaper = new CustomShaperCompilingExpressionVisitor( - dataReaderParameter, resultCoordinatorParameter, TrackQueryResults) + dataReaderParameter, resultCoordinatorParameter, IsTracking) .Visit(shaper); if (selectExpression.IsNonComposedFromSql()) @@ -72,7 +69,7 @@ protected override Expression VisitShapedQueryExpression(ShapedQueryExpression s var shaperLambda = (LambdaExpression)shaper; return Expression.New( - (Async + (IsAsync ? typeof(AsyncQueryingEnumerable<>) : typeof(QueryingEnumerable<>)).MakeGenericType(shaperLambda.ReturnType).GetConstructors()[0], Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryOptimizer.cs b/src/EFCore.Relational/Query/RelationalShapedQueryOptimizer.cs new file mode 100644 index 00000000000..cce3887758a --- /dev/null +++ b/src/EFCore.Relational/Query/RelationalShapedQueryOptimizer.cs @@ -0,0 +1,41 @@ +// 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.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Query.Internal; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public class RelationalShapedQueryOptimizer : ShapedQueryOptimizer + { + public RelationalShapedQueryOptimizer( + QueryCompilationContext queryCompilationContext, + ISqlExpressionFactory sqlExpressionFactory) + { + UseRelationalNulls = RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).UseRelationalNulls; + SqlExpressionFactory = sqlExpressionFactory; + } + + protected virtual ISqlExpressionFactory SqlExpressionFactory { get; } + protected virtual bool UseRelationalNulls { get; } + + public override Expression Visit(Expression query) + { + query = base.Visit(query); + query = new SelectExpressionProjectionApplyingExpressionVisitor().Visit(query); + query = new CollectionJoinApplyingExpressionVisitor().Visit(query); + query = new SelectExpressionTableAliasUniquifyingExpressionVisitor().Visit(query); + + if (!UseRelationalNulls) + { + query = new NullSemanticsRewritingVisitor(SqlExpressionFactory).Visit(query); + } + + query = new SqlExpressionOptimizingVisitor(SqlExpressionFactory, UseRelationalNulls).Visit(query); + query = new NullComparisonTransformingExpressionVisitor().Visit(query); + + return query; + } + } +} diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs similarity index 97% rename from src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitor.cs rename to src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index 40a78652d37..0a6bb36f8e7 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -5,17 +5,14 @@ using System.Diagnostics; using System.Linq; using System.Linq.Expressions; -using System.Reflection; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class RelationalSqlTranslatingExpressionVisitor : ExpressionVisitor { @@ -309,7 +306,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp var subqueryTranslation = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); if (subqueryTranslation != null) { - if (subqueryTranslation.ResultType == ResultType.Enumerable) + if (subqueryTranslation.ResultCardinality == ResultCardinality.Enumerable) { return null; } @@ -330,7 +327,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return subquery.Projection[0].Expression; } - return new SubSelectExpression(subquery); + return new ScalarSubqueryExpression(subquery); } // MethodCall translators diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs similarity index 76% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressionFactory.cs rename to src/EFCore.Relational/Query/SqlExpressionFactory.cs index a47f41f4769..a4526f3c083 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -6,25 +6,23 @@ using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class SqlExpressionFactory : ISqlExpressionFactory { private readonly IRelationalTypeMappingSource _typeMappingSource; private readonly RelationalTypeMapping _boolTypeMapping; - public SqlExpressionFactory(IRelationalTypeMappingSource typeMappingSource) + public SqlExpressionFactory(SqlExpressionFactoryDependencies dependencies) { - _typeMappingSource = typeMappingSource; - _boolTypeMapping = typeMappingSource.FindMapping(typeof(bool)); + _typeMappingSource = dependencies.TypeMappingSource; + _boolTypeMapping = _typeMappingSource.FindMapping(typeof(bool)); } - public SqlExpression ApplyDefaultTypeMapping(SqlExpression sqlExpression) + public virtual SqlExpression ApplyDefaultTypeMapping(SqlExpression sqlExpression) => sqlExpression == null || sqlExpression.TypeMapping != null ? sqlExpression : ApplyTypeMapping(sqlExpression, _typeMappingSource.FindMapping(sqlExpression.Type)); @@ -183,7 +181,7 @@ public virtual RelationalTypeMapping GetTypeMappingForValue(object value) public virtual RelationalTypeMapping FindMapping(Type type) => _typeMappingSource.FindMapping(type); - public SqlBinaryExpression MakeBinary( + public virtual SqlBinaryExpression MakeBinary( ExpressionType operatorType, SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping) { var returnType = left.Type; @@ -205,73 +203,73 @@ public SqlBinaryExpression MakeBinary( new SqlBinaryExpression(operatorType, left, right, returnType, null), typeMapping); } - public SqlBinaryExpression Equal(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression Equal(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.Equal, left, right, null); - public SqlBinaryExpression NotEqual(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression NotEqual(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.NotEqual, left, right, null); - public SqlBinaryExpression GreaterThan(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression GreaterThan(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.GreaterThan, left, right, null); - public SqlBinaryExpression GreaterThanOrEqual(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression GreaterThanOrEqual(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.GreaterThanOrEqual, left, right, null); - public SqlBinaryExpression LessThan(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression LessThan(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.LessThan, left, right, null); - public SqlBinaryExpression LessThanOrEqual(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression LessThanOrEqual(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.LessThanOrEqual, left, right, null); - public SqlBinaryExpression AndAlso(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression AndAlso(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.AndAlso, left, right, null); - public SqlBinaryExpression OrElse(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression OrElse(SqlExpression left, SqlExpression right) => MakeBinary(ExpressionType.OrElse, left, right, null); - public SqlBinaryExpression Add(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Add(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.Add, left, right, typeMapping); - public SqlBinaryExpression Subtract(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Subtract(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.Subtract, left, right, typeMapping); - public SqlBinaryExpression Multiply(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Multiply(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.Multiply, left, right, typeMapping); - public SqlBinaryExpression Divide(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Divide(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.Divide, left, right, typeMapping); - public SqlBinaryExpression Modulo(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Modulo(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.Modulo, left, right, typeMapping); - public SqlBinaryExpression And(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression And(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.And, left, right, typeMapping); - public SqlBinaryExpression Or(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Or(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.Or, left, right, typeMapping); - public SqlBinaryExpression Coalesce(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) + public virtual SqlBinaryExpression Coalesce(SqlExpression left, SqlExpression right, RelationalTypeMapping typeMapping = null) => MakeBinary(ExpressionType.Coalesce, left, right, typeMapping); - private SqlUnaryExpression MakeUnary(ExpressionType operatorType, SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null) + public virtual SqlUnaryExpression MakeUnary(ExpressionType operatorType, SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null) => (SqlUnaryExpression)ApplyTypeMapping(new SqlUnaryExpression(operatorType, operand, type, null), typeMapping); - public SqlUnaryExpression IsNull(SqlExpression operand) + public virtual SqlUnaryExpression IsNull(SqlExpression operand) => MakeUnary(ExpressionType.Equal, operand, typeof(bool)); - public SqlUnaryExpression IsNotNull(SqlExpression operand) + public virtual SqlUnaryExpression IsNotNull(SqlExpression operand) => MakeUnary(ExpressionType.NotEqual, operand, typeof(bool)); - public SqlUnaryExpression Convert(SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null) + public virtual SqlUnaryExpression Convert(SqlExpression operand, Type type, RelationalTypeMapping typeMapping = null) => MakeUnary(ExpressionType.Convert, operand, type, typeMapping); - public SqlUnaryExpression Not(SqlExpression operand) + public virtual SqlUnaryExpression Not(SqlExpression operand) => MakeUnary(ExpressionType.Not, operand, typeof(bool)); - public SqlUnaryExpression Negate(SqlExpression operand) + public virtual SqlUnaryExpression Negate(SqlExpression operand) => MakeUnary(ExpressionType.Negate, operand, operand.Type, operand.TypeMapping); - public CaseExpression Case(SqlExpression operand, params CaseWhenClause[] whenClauses) + public virtual CaseExpression Case(SqlExpression operand, params CaseWhenClause[] whenClauses) { var operandTypeMapping = operand.TypeMapping ?? whenClauses.Select(wc => wc.Test.TypeMapping).FirstOrDefault(t => t != null) @@ -292,7 +290,7 @@ public CaseExpression Case(SqlExpression operand, params CaseWhenClause[] whenCl return new CaseExpression(operand, typeMappedWhenClauses); } - public CaseExpression Case(IReadOnlyList whenClauses, SqlExpression elseResult) + public virtual CaseExpression Case(IReadOnlyList whenClauses, SqlExpression elseResult) { var resultTypeMapping = elseResult?.TypeMapping ?? whenClauses.Select(wc => wc.Result.TypeMapping).FirstOrDefault(t => t != null); @@ -311,8 +309,8 @@ public CaseExpression Case(IReadOnlyList whenClauses, SqlExpress return new CaseExpression(typeMappedWhenClauses, elseResult); } - public SqlFunctionExpression Function( - string functionName, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) + public virtual SqlFunctionExpression Function( + string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) { var typeMappedArguments = new List(); @@ -322,14 +320,14 @@ public SqlFunctionExpression Function( } return new SqlFunctionExpression( - functionName, + name, typeMappedArguments, returnType, typeMapping); } - public SqlFunctionExpression Function( - string schema, string functionName, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) + public virtual SqlFunctionExpression Function( + string schema, string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) { var typeMappedArguments = new List(); foreach (var argument in arguments) @@ -339,14 +337,14 @@ public SqlFunctionExpression Function( return new SqlFunctionExpression( schema, - functionName, + name, typeMappedArguments, returnType, typeMapping); } - public SqlFunctionExpression Function( - SqlExpression instance, string functionName, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) + public virtual SqlFunctionExpression Function( + SqlExpression instance, string name, IEnumerable arguments, Type returnType, RelationalTypeMapping typeMapping = null) { instance = ApplyDefaultTypeMapping(instance); var typeMappedArguments = new List(); @@ -357,25 +355,25 @@ public SqlFunctionExpression Function( return new SqlFunctionExpression( instance, - functionName, + name, typeMappedArguments, returnType, typeMapping); } - public SqlFunctionExpression Function(string functionName, Type returnType, RelationalTypeMapping typeMapping = null) - => new SqlFunctionExpression(functionName, returnType, typeMapping); + public virtual SqlFunctionExpression Function(string name, Type returnType, RelationalTypeMapping typeMapping = null) + => new SqlFunctionExpression(name, returnType, typeMapping); - public SqlFunctionExpression Function(string schema, string functionName, Type returnType, RelationalTypeMapping typeMapping = null) - => new SqlFunctionExpression(schema, functionName, returnType, typeMapping); + public virtual SqlFunctionExpression Function(string schema, string name, Type returnType, RelationalTypeMapping typeMapping = null) + => new SqlFunctionExpression(schema, name, returnType, typeMapping); - public SqlFunctionExpression Function(SqlExpression instance, string functionName, Type returnType, RelationalTypeMapping typeMapping = null) - => new SqlFunctionExpression(ApplyDefaultTypeMapping(instance), functionName, returnType, typeMapping); + public virtual SqlFunctionExpression Function(SqlExpression instance, string name, Type returnType, RelationalTypeMapping typeMapping = null) + => new SqlFunctionExpression(ApplyDefaultTypeMapping(instance), name, returnType, typeMapping); - public ExistsExpression Exists(SelectExpression subquery, bool negated) + public virtual ExistsExpression Exists(SelectExpression subquery, bool negated) => new ExistsExpression(subquery, negated, _boolTypeMapping); - public InExpression In(SqlExpression item, SqlExpression values, bool negated) + public virtual InExpression In(SqlExpression item, SqlExpression values, bool negated) { var typeMapping = item.TypeMapping ?? _typeMappingSource.FindMapping(item.Type); @@ -385,7 +383,7 @@ public InExpression In(SqlExpression item, SqlExpression values, bool negated) return new InExpression(item, negated, values, _boolTypeMapping); } - public InExpression In(SqlExpression item, SelectExpression subquery, bool negated) + public virtual InExpression In(SqlExpression item, SelectExpression subquery, bool negated) { var typeMapping = subquery.Projection.Single().Expression.TypeMapping; @@ -398,16 +396,16 @@ public InExpression In(SqlExpression item, SelectExpression subquery, bool negat return new InExpression(item, negated, subquery, _boolTypeMapping); } - public LikeExpression Like(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar = null) + public virtual LikeExpression Like(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar = null) => (LikeExpression)ApplyDefaultTypeMapping(new LikeExpression(match, pattern, escapeChar, null)); - public SqlFragmentExpression Fragment(string sql) + public virtual SqlFragmentExpression Fragment(string sql) => new SqlFragmentExpression(sql); - public SqlConstantExpression Constant(object value, RelationalTypeMapping typeMapping = null) + public virtual SqlConstantExpression Constant(object value, RelationalTypeMapping typeMapping = null) => new SqlConstantExpression(Expression.Constant(value), typeMapping); - public SelectExpression Select(SqlExpression projection) + public virtual SelectExpression Select(SqlExpression projection) { var selectExpression = new SelectExpression( alias: null, @@ -427,7 +425,7 @@ public SelectExpression Select(SqlExpression projection) return selectExpression; } - public SelectExpression Select(IEntityType entityType) + public virtual SelectExpression Select(IEntityType entityType) { var selectExpression = new SelectExpression(entityType); AddDiscriminator(selectExpression, entityType); @@ -435,7 +433,7 @@ public SelectExpression Select(IEntityType entityType) return selectExpression; } - public SelectExpression Select(IEntityType entityType, string sql, Expression sqlArguments) + public virtual SelectExpression Select(IEntityType entityType, string sql, Expression sqlArguments) { var selectExpression = new SelectExpression(entityType, sql, sqlArguments); AddDiscriminator(selectExpression, entityType); diff --git a/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs b/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs new file mode 100644 index 00000000000..2b4f4efc2f8 --- /dev/null +++ b/src/EFCore.Relational/Query/SqlExpressionFactoryDependencies.cs @@ -0,0 +1,76 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +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 a single instance + /// is used by many instances. The implementation must be thread-safe. + /// This service cannot depend on services registered as . + /// + /// + public sealed class SqlExpressionFactoryDependencies + { + /// + /// + /// 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 SqlExpressionFactoryDependencies(IRelationalTypeMappingSource typeMappingSource) + { + Check.NotNull(typeMappingSource, nameof(typeMappingSource)); + + TypeMappingSource = typeMappingSource; + } + + /// + /// The type mapping source. + /// + public IRelationalTypeMappingSource TypeMappingSource { 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 SqlExpressionFactoryDependencies With([NotNull] IRelationalTypeMappingSource typeMappingSource) + => new SqlExpressionFactoryDependencies(typeMappingSource); + } +} diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressionOptimizingVisitor.cs b/src/EFCore.Relational/Query/SqlExpressionOptimizingVisitor.cs similarity index 98% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressionOptimizingVisitor.cs rename to src/EFCore.Relational/Query/SqlExpressionOptimizingVisitor.cs index 83bd2abbf09..2717815856c 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressionOptimizingVisitor.cs +++ b/src/EFCore.Relational/Query/SqlExpressionOptimizingVisitor.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class SqlExpressionOptimizingVisitor : ExpressionVisitor { diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressionVisitor.cs b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs similarity index 93% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressionVisitor.cs rename to src/EFCore.Relational/Query/SqlExpressionVisitor.cs index 360e1ebb419..3672d4525e7 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public abstract class SqlExpressionVisitor : ExpressionVisitor { @@ -66,7 +66,7 @@ protected override Expression VisitExtension(Expression extensionExpression) case SqlParameterExpression sqlParameterExpression: return VisitSqlParameter(sqlParameterExpression); - case SubSelectExpression subSelectExpression: + case ScalarSubqueryExpression subSelectExpression: return VisitSubSelect(subSelectExpression); case TableExpression tableExpression: @@ -95,6 +95,6 @@ protected override Expression VisitExtension(Expression extensionExpression) protected abstract Expression VisitTable(TableExpression tableExpression); protected abstract Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression); protected abstract Expression VisitLike(LikeExpression likeExpression); - protected abstract Expression VisitSubSelect(SubSelectExpression subSelectExpression); + protected abstract Expression VisitSubSelect(ScalarSubqueryExpression scalarSubqueryExpression); } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/CaseExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs similarity index 93% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/CaseExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs index a2f63d6f105..04c88efb923 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/CaseExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs @@ -5,9 +5,8 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class CaseExpression : SqlExpression { @@ -38,9 +37,9 @@ private CaseExpression( ElseResult = elseResult; } - public SqlExpression Operand { get; } - public IReadOnlyList WhenClauses => _whenClauses; - public SqlExpression ElseResult { get; } + public virtual SqlExpression Operand { get; } + public virtual IReadOnlyList WhenClauses => _whenClauses; + public virtual SqlExpression ElseResult { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/CaseWhenClause.cs b/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs similarity index 83% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/CaseWhenClause.cs rename to src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs index 187360cfcd1..0e0a722d9c1 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/CaseWhenClause.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CaseWhenClause.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class CaseWhenClause { @@ -13,8 +13,8 @@ public CaseWhenClause(SqlExpression test, SqlExpression result) Result = result; } - public SqlExpression Test { get; } - public SqlExpression Result { get; } + public virtual SqlExpression Test { get; } + public virtual SqlExpression Result { get; } public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/ColumnExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs similarity index 90% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/ColumnExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs index 433b2ea2366..dc76481d53c 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/ColumnExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs @@ -5,11 +5,10 @@ using System.Diagnostics; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { [DebuggerDisplay("{DebuggerDisplay(),nq}")] public class ColumnExpression : SqlExpression @@ -30,7 +29,7 @@ internal ColumnExpression(ProjectionExpression subqueryProjection, TableExpressi private static bool IsNullableProjection(ProjectionExpression projectionExpression) => projectionExpression.Expression switch { - ColumnExpression columnExpression => columnExpression.Nullable, + ColumnExpression columnExpression => columnExpression.IsNullable, SqlConstantExpression sqlConstantExpression => sqlConstantExpression.Value == null, _ => true, }; @@ -44,19 +43,19 @@ private ColumnExpression(string name, TableExpressionBase table, Type type, Rela Name = name; Table = table; - Nullable = nullable; + IsNullable = nullable; } public string Name { get; } public TableExpressionBase Table { get; } - public bool Nullable { get; } + public bool IsNullable { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { var newTable = (TableExpressionBase)visitor.Visit(Table); return newTable != Table - ? new ColumnExpression(Name, newTable, Type, TypeMapping, Nullable) + ? new ColumnExpression(Name, newTable, Type, TypeMapping, IsNullable) : this; } @@ -82,9 +81,9 @@ private bool Equals(ColumnExpression columnExpression) => base.Equals(columnExpression) && string.Equals(Name, columnExpression.Name) && Table.Equals(columnExpression.Table) - && Nullable == columnExpression.Nullable; + && IsNullable == columnExpression.IsNullable; - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Name, Table, Nullable); + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Name, Table, IsNullable); private string DebuggerDisplay() => $"{Table.Alias}.{Name}"; } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/CrossJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs similarity index 86% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/CrossJoinExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs index 26af574c769..94a85fa4e66 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/CrossJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs @@ -2,9 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class CrossJoinExpression : JoinExpressionBase { @@ -16,7 +15,7 @@ public CrossJoinExpression(TableExpressionBase table) protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((TableExpressionBase)visitor.Visit(Table)); - public CrossJoinExpression Update(TableExpressionBase table) + public virtual CrossJoinExpression Update(TableExpressionBase table) => table != Table ? new CrossJoinExpression(table) : this; diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/ExistsExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs similarity index 76% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/ExistsExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs index d9f4106fa74..03c5fa71023 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/ExistsExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ExistsExpression.cs @@ -3,10 +3,9 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class ExistsExpression : SqlExpression { @@ -14,24 +13,24 @@ public ExistsExpression(SelectExpression subquery, bool negated, RelationalTypeM : base(typeof(bool), typeMapping) { Subquery = subquery; - Negated = negated; + IsNegated = negated; } - public SelectExpression Subquery { get; } - public bool Negated { get; } + public virtual SelectExpression Subquery { get; } + public virtual bool IsNegated { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SelectExpression)visitor.Visit(Subquery)); - public ExistsExpression Update(SelectExpression subquery) + public virtual ExistsExpression Update(SelectExpression subquery) => subquery != Subquery - ? new ExistsExpression(subquery, Negated, TypeMapping) + ? new ExistsExpression(subquery, IsNegated, TypeMapping) : this; public override void Print(ExpressionPrinter expressionPrinter) { - if (Negated) + if (IsNegated) { expressionPrinter.StringBuilder.Append("NOT "); } @@ -54,8 +53,8 @@ public override bool Equals(object obj) private bool Equals(ExistsExpression existsExpression) => base.Equals(existsExpression) && Subquery.Equals(existsExpression.Subquery) - && Negated == existsExpression.Negated; + && IsNegated == existsExpression.IsNegated; - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Subquery, Negated); + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Subquery, IsNegated); } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/FromSqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs similarity index 85% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/FromSqlExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs index b9f04dc8c0d..aa62dd9c986 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/FromSqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs @@ -4,9 +4,8 @@ using System; using System.Linq.Expressions; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class FromSqlExpression : TableExpressionBase { @@ -17,8 +16,8 @@ public FromSqlExpression([NotNull] string sql, Expression arguments, [NotNull] s Arguments = arguments; } - public string Sql { get; } - public Expression Arguments { get; } + public virtual string Sql { get; } + public virtual Expression Arguments { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) => this; diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/InExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs similarity index 79% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/InExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/InExpression.cs index 62df14cc49a..e05ee9db9f0 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/InExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs @@ -4,10 +4,9 @@ using System; using System.Collections; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class InExpression : SqlExpression { @@ -26,15 +25,15 @@ private InExpression(SqlExpression item, bool negated, SqlExpression values, Sel : base(typeof(bool), typeMapping) { Item = item; - Negated = negated; + IsNegated = negated; Subquery = subquery; Values = values; } - public SqlExpression Item { get; } - public bool Negated { get; } - public SqlExpression Values { get; } - public SelectExpression Subquery { get; } + public virtual SqlExpression Item { get; } + public virtual bool IsNegated { get; } + public virtual SqlExpression Values { get; } + public virtual SelectExpression Subquery { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { @@ -45,17 +44,17 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(newItem, values, subquery); } - public InExpression Negate() => new InExpression(Item, !Negated, Values, Subquery, TypeMapping); + public virtual InExpression Negate() => new InExpression(Item, !IsNegated, Values, Subquery, TypeMapping); - public InExpression Update(SqlExpression item, SqlExpression values, SelectExpression subquery) + public virtual InExpression Update(SqlExpression item, SqlExpression values, SelectExpression subquery) => item != Item || subquery != Subquery || values != Values - ? new InExpression(item, Negated, values, subquery, TypeMapping) + ? new InExpression(item, IsNegated, values, subquery, TypeMapping) : this; public override void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.Visit(Item); - expressionPrinter.StringBuilder.Append(Negated ? " NOT IN " : " IN "); + expressionPrinter.StringBuilder.Append(IsNegated ? " NOT IN " : " IN "); expressionPrinter.StringBuilder.Append("("); if (Values is SqlConstantExpression constantValuesExpression @@ -90,10 +89,10 @@ public override bool Equals(object obj) private bool Equals(InExpression inExpression) => base.Equals(inExpression) && Item.Equals(inExpression.Item) - && Negated.Equals(inExpression.Negated) + && IsNegated.Equals(inExpression.IsNegated) && (Values == null ? inExpression.Values == null : Values.Equals(inExpression.Values)) && (Subquery == null ? inExpression.Subquery == null : Subquery.Equals(inExpression.Subquery)); - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Item, Negated, Values, Subquery); + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Item, IsNegated, Values, Subquery); } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/InnerJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs similarity index 87% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/InnerJoinExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs index 559affd7f14..0a0955006a3 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/InnerJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs @@ -2,9 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class InnerJoinExpression : PredicateJoinExpressionBase { @@ -21,7 +20,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(table, joinPredicate); } - public InnerJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate) + public virtual InnerJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate) => table != Table || joinPredicate != JoinPredicate ? new InnerJoinExpression(table, joinPredicate) : this; diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/JoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs similarity index 87% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/JoinExpressionBase.cs rename to src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs index b829a90b0f0..a2ece867fb6 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/JoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class JoinExpressionBase : TableExpressionBase { @@ -13,7 +13,7 @@ protected JoinExpressionBase(TableExpressionBase table) Table = table; } - public TableExpressionBase Table { get; } + public virtual TableExpressionBase Table { get; } public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/LeftJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs similarity index 87% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/LeftJoinExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs index 3b68836061c..7895c02400a 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/LeftJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs @@ -2,9 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class LeftJoinExpression : PredicateJoinExpressionBase { @@ -21,7 +20,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(table, joinPredicate); } - public LeftJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate) + public virtual LeftJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate) => table != Table || joinPredicate != JoinPredicate ? new LeftJoinExpression(table, joinPredicate) : this; diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/LikeExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs similarity index 85% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/LikeExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs index 7749c9f9f6c..e4aa88c0516 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/LikeExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/LikeExpression.cs @@ -3,10 +3,9 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class LikeExpression : SqlExpression { @@ -18,9 +17,9 @@ public LikeExpression(SqlExpression match, SqlExpression pattern, SqlExpression EscapeChar = escapeChar; } - public SqlExpression Match { get; } - public SqlExpression Pattern { get; } - public SqlExpression EscapeChar { get; } + public virtual SqlExpression Match { get; } + public virtual SqlExpression Pattern { get; } + public virtual SqlExpression EscapeChar { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { @@ -31,7 +30,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(match, pattern, escapeChar); } - public LikeExpression Update(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar) + public virtual LikeExpression Update(SqlExpression match, SqlExpression pattern, SqlExpression escapeChar) => match != Match || pattern != Pattern || escapeChar != EscapeChar ? new LikeExpression(match, pattern, escapeChar, TypeMapping) : this; diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/OrderingExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs similarity index 65% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/OrderingExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs index f3568e55a3f..e2869be33f1 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/OrderingExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs @@ -3,37 +3,35 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class OrderingExpression : Expression, IPrintable { public OrderingExpression(SqlExpression expression, bool ascending) { Expression = expression; - Ascending = ascending; + IsAscending = ascending; } - public SqlExpression Expression { get; } - public bool Ascending { get; } + public virtual SqlExpression Expression { get; } + public virtual bool IsAscending { get; } public override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => Expression.Type; protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression)); - public OrderingExpression Update(SqlExpression expression) + public virtual OrderingExpression Update(SqlExpression expression) => expression != Expression - ? new OrderingExpression(expression, Ascending) + ? new OrderingExpression(expression, IsAscending) : this; - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.Visit(Expression); - expressionPrinter.StringBuilder.Append(Ascending ? " ASC" : " DESC"); + expressionPrinter.StringBuilder.Append(IsAscending ? " ASC" : " DESC"); } public override bool Equals(object obj) @@ -44,8 +42,8 @@ public override bool Equals(object obj) private bool Equals(OrderingExpression orderingExpression) => Expression.Equals(orderingExpression.Expression) - && Ascending == orderingExpression.Ascending; + && IsAscending == orderingExpression.IsAscending; - public override int GetHashCode() => HashCode.Combine(Expression, Ascending); + public override int GetHashCode() => HashCode.Combine(Expression, IsAscending); } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/PredicateJoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs similarity index 88% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/PredicateJoinExpressionBase.cs rename to src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs index 39719dc6da0..5a86222f8f2 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/PredicateJoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class PredicateJoinExpressionBase : JoinExpressionBase { @@ -13,7 +13,7 @@ protected PredicateJoinExpressionBase(TableExpressionBase table, SqlExpression j JoinPredicate = joinPredicate; } - public SqlExpression JoinPredicate { get; } + public virtual SqlExpression JoinPredicate { get; } public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/ProjectionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs similarity index 80% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/ProjectionExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs index c60ede10807..85a698774eb 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/ProjectionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs @@ -3,10 +3,8 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class ProjectionExpression : Expression, IPrintable { @@ -16,8 +14,8 @@ public ProjectionExpression(SqlExpression expression, string alias) Alias = alias; } - public string Alias { get; } - public SqlExpression Expression { get; } + public virtual string Alias { get; } + public virtual SqlExpression Expression { get; } public override Type Type => Expression.Type; public override ExpressionType NodeType => ExpressionType.Extension; @@ -25,12 +23,12 @@ public ProjectionExpression(SqlExpression expression, string alias) protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Expression)); - public ProjectionExpression Update(SqlExpression expression) + public virtual ProjectionExpression Update(SqlExpression expression) => expression != Expression ? new ProjectionExpression(expression, Alias) : this; - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.Visit(Expression); if (!string.Equals(string.Empty, Alias) diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SubSelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs similarity index 69% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SubSelectExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs index 33edd19178f..ba539dd2f70 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SubSelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ScalarSubqueryExpression.cs @@ -3,13 +3,12 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { - public class SubSelectExpression : SqlExpression + public class ScalarSubqueryExpression : SqlExpression { - public SubSelectExpression(SelectExpression subquery) + public ScalarSubqueryExpression(SelectExpression subquery) : base(Verify(subquery).Projection[0].Type, subquery.Projection[0].Expression.TypeMapping) { Subquery = subquery; @@ -24,14 +23,14 @@ private static SelectExpression Verify(SelectExpression selectExpression) return selectExpression; } - public SelectExpression Subquery { get; } + public virtual SelectExpression Subquery { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SelectExpression)visitor.Visit(Subquery)); - public SubSelectExpression Update(SelectExpression subquery) + public virtual ScalarSubqueryExpression Update(SelectExpression subquery) => subquery != Subquery - ? new SubSelectExpression(subquery) + ? new ScalarSubqueryExpression(subquery) : this; public override void Print(ExpressionPrinter expressionPrinter) @@ -46,12 +45,12 @@ public override void Print(ExpressionPrinter expressionPrinter) public override bool Equals(object obj) => obj != null && (ReferenceEquals(this, obj) - || obj is SubSelectExpression subSelectExpression + || obj is ScalarSubqueryExpression subSelectExpression && Equals(subSelectExpression)); - private bool Equals(SubSelectExpression subSelectExpression) - => base.Equals(subSelectExpression) - && Subquery.Equals(subSelectExpression.Subquery); + private bool Equals(ScalarSubqueryExpression scalarSubqueryExpression) + => base.Equals(scalarSubqueryExpression) + && Subquery.Equals(scalarSubqueryExpression.Subquery); public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Subquery); } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs similarity index 96% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 438ad939795..ac4929d33f8 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -8,10 +8,8 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SelectExpression : TableExpressionBase { @@ -34,7 +32,7 @@ private readonly IDictionary Orderings => _orderings; public ISet Tags { get; private set; } = new HashSet(); public SqlExpression Predicate { get; private set; } - public SqlExpression HavingExpression { get; private set; } + public SqlExpression Having { get; private set; } public SqlExpression Limit { get; private set; } public SqlExpression Offset { get; private set; } public bool IsDistinct { get; private set; } @@ -120,7 +118,7 @@ public bool IsNonComposedFromSql() && !IsDistinct && Predicate == null && GroupBy.Count == 0 - && HavingExpression == null + && Having == null && Orderings.Count == 0 && Tables.Count == 1 && Tables[0] is FromSqlExpression fromSql @@ -150,7 +148,7 @@ public void ApplyProjection() else { result[keyValuePair.Key] = Constant(AddToProjection( - (SqlExpression)keyValuePair.Value, keyValuePair.Key.LastMember?.Name)); + (SqlExpression)keyValuePair.Value, keyValuePair.Key.Last?.Name)); } } @@ -241,11 +239,11 @@ public void ApplyPredicate(SqlExpression expression) if (_groupBy.Count > 0) { - HavingExpression = HavingExpression == null + Having = Having == null ? expression : new SqlBinaryExpression( ExpressionType.AndAlso, - HavingExpression, + Having, expression, typeof(bool), expression.TypeMapping); @@ -374,7 +372,7 @@ public void ReverseOrderings() _orderings.Add( new OrderingExpression( existingOrdering[i].Expression, - !existingOrdering[i].Ascending)); + !existingOrdering[i].IsAscending)); } } @@ -417,7 +415,7 @@ public Expression ApplySetOperation( { IsDistinct = IsDistinct, Predicate = Predicate, - HavingExpression = HavingExpression, + Having = Having, Offset = Offset, Limit = Limit, SetOperationType = SetOperationType @@ -457,7 +455,7 @@ public Expression ApplySetOperation( } if (joinedMapping.Value1 is ColumnExpression && joinedMapping.Value2 is ColumnExpression - || joinedMapping.Value1 is SubSelectExpression && joinedMapping.Value2 is SubSelectExpression) + || joinedMapping.Value1 is ScalarSubqueryExpression && joinedMapping.Value2 is ScalarSubqueryExpression) { handleColumnMapping( joinedMapping.Key, @@ -474,7 +472,7 @@ public Expression ApplySetOperation( Limit = null; IsDistinct = false; Predicate = null; - HavingExpression = null; + Having = null; _orderings.Clear(); _tables.Clear(); _tables.Add(select1); @@ -532,7 +530,7 @@ void handleColumnMapping( { // The actual columns may actually be different, but we don't care as long as the type and alias // coming out of the two operands are the same - var alias = projectionMember.LastMember?.Name; + var alias = projectionMember.Last?.Name; select1.AddToProjection(innerColumn1, alias); select2.AddToProjection(innerColumn2, alias); _projectionMapping[projectionMember] = innerColumn1; @@ -546,7 +544,7 @@ public IDictionary PushdownIntoSubquery() { IsDistinct = IsDistinct, Predicate = Predicate, - HavingExpression = HavingExpression, + Having = Having, Offset = Offset, Limit = Limit, SetOperationType = SetOperationType @@ -659,7 +657,7 @@ ColumnExpression liftProjectionFromSubquery(SqlExpression projection) Limit = null; IsDistinct = false; Predicate = null; - HavingExpression = null; + Having = null; SetOperationType = SetOperationType.None; _tables.Clear(); _tables.Add(subquery); @@ -932,13 +930,13 @@ public void AddInnerJoin(SelectExpression innerSelectExpression, SqlExpression j var projectionMapping = new Dictionary(); foreach (var projection in _projectionMapping) { - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] = projection.Value; + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; } var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); foreach (var projection in innerSelectExpression._projectionMapping) { - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] = projection.Value; + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projection.Value; } _projectionMapping = projectionMapping; @@ -973,7 +971,7 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo var projectionMapping = new Dictionary(); foreach (var projection in _projectionMapping) { - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] = projection.Value; + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; } var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); @@ -989,7 +987,7 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo projectionToAdd = column.MakeNullable(); } - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] = projectionToAdd; + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projectionToAdd; } _projectionMapping = projectionMapping; @@ -1022,13 +1020,13 @@ public void AddCrossJoin(SelectExpression innerSelectExpression, Type transparen var projectionMapping = new Dictionary(); foreach (var projection in _projectionMapping) { - projectionMapping[projection.Key.ShiftMember(outerMemberInfo)] = projection.Value; + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; } var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); foreach (var projection in innerSelectExpression._projectionMapping) { - projectionMapping[projection.Key.ShiftMember(innerMemberInfo)] = projection.Value; + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projection.Value; } _projectionMapping = projectionMapping; @@ -1093,7 +1091,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) _groupBy.Clear(); _groupBy.AddRange(GroupBy.Select(e => (SqlExpression)visitor.Visit(e))); - HavingExpression = (SqlExpression)visitor.Visit(HavingExpression); + Having = (SqlExpression)visitor.Visit(Having); var orderings = _orderings.ToList(); _orderings.Clear(); @@ -1152,8 +1150,8 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) groupBy.Add(newGroupingKey); } - var havingExpression = (SqlExpression)visitor.Visit(HavingExpression); - changed |= havingExpression != HavingExpression; + var havingExpression = (SqlExpression)visitor.Visit(Having); + changed |= havingExpression != Having; var orderings = new List(); foreach (var ordering in _orderings) @@ -1175,7 +1173,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) { _projectionMapping = projectionMapping, Predicate = predicate, - HavingExpression = havingExpression, + Having = havingExpression, Offset = offset, Limit = limit, IsDistinct = IsDistinct, @@ -1249,8 +1247,8 @@ private bool Equals(SelectExpression selectExpression) return false; } - if (!(HavingExpression == null && selectExpression.HavingExpression == null - || HavingExpression != null && Predicate.Equals(selectExpression.HavingExpression))) + if (!(Having == null && selectExpression.Having == null + || Having != null && Predicate.Equals(selectExpression.Having))) { return false; } @@ -1298,7 +1296,7 @@ public SelectExpression Update( { _projectionMapping = projectionMapping, Predicate = predicate, - HavingExpression = havingExpression, + Having = havingExpression, Offset = offset, Limit = limit, IsDistinct = distinct, @@ -1331,7 +1329,7 @@ public override int GetHashCode() hash.Add(groupingKey); } - hash.Add(HavingExpression); + hash.Add(Having); foreach (var ordering in _orderings) { @@ -1419,10 +1417,10 @@ public override void Print(ExpressionPrinter expressionPrinter) expressionPrinter.VisitList(GroupBy); } - if (HavingExpression != null) + if (Having != null) { expressionPrinter.StringBuilder.AppendLine().Append("HAVING "); - expressionPrinter.Visit(HavingExpression); + expressionPrinter.Visit(Having); } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlBinaryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs similarity index 92% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlBinaryExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs index 93f6caa810c..689b1aefa2a 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlBinaryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs @@ -4,11 +4,10 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlBinaryExpression : SqlExpression { @@ -59,9 +58,9 @@ public SqlBinaryExpression( Right = right; } - public ExpressionType OperatorType { get; } - public SqlExpression Left { get; } - public SqlExpression Right { get; } + public virtual ExpressionType OperatorType { get; } + public virtual SqlExpression Left { get; } + public virtual SqlExpression Right { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { @@ -71,7 +70,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(left, right); } - public SqlBinaryExpression Update(SqlExpression left, SqlExpression right) + public virtual SqlBinaryExpression Update(SqlExpression left, SqlExpression right) => left != Left || right != Right ? new SqlBinaryExpression(OperatorType, left, right, Type, TypeMapping) : this; diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlConstantExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs similarity index 85% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlConstantExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs index 3a31afe1f1b..9cf6b430f84 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlConstantExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs @@ -2,12 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlConstantExpression : SqlExpression { @@ -19,9 +17,9 @@ public SqlConstantExpression(ConstantExpression constantExpression, RelationalTy _constantExpression = constantExpression; } - public object Value => _constantExpression.Value; + public virtual object Value => _constantExpression.Value; - public SqlExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) + public virtual SqlExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) => new SqlConstantExpression(_constantExpression, typeMapping); protected override Expression VisitChildren(ExpressionVisitor visitor) => this; public override void Print(ExpressionPrinter expressionPrinter) => Print(Value, expressionPrinter); diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs similarity index 84% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs index bd21a829954..cdf1e4749d3 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs @@ -3,11 +3,9 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class SqlExpression : Expression, IPrintable { @@ -18,7 +16,7 @@ protected SqlExpression(Type type, RelationalTypeMapping typeMapping) } public override Type Type { get; } - public RelationalTypeMapping TypeMapping { get; } + public virtual RelationalTypeMapping TypeMapping { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) => throw new InvalidOperationException("VisitChildren must be overridden in class deriving from SqlExpression"); diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlFragmentExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs similarity index 90% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlFragmentExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs index affa428187e..f922ab1cff2 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlFragmentExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs @@ -3,9 +3,8 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlFragmentExpression : SqlExpression { diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs similarity index 71% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlFunctionExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs index 724996a8656..3208462fefc 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs @@ -5,75 +5,74 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlFunctionExpression : SqlExpression { // niladic public SqlFunctionExpression( - string functionName, + string name, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema: null, functionName, niladic: true, arguments: null, builtIn: true, type, typeMapping) + : this(instance: null, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping) { } // niladic public SqlFunctionExpression( string schema, - string functionName, + string name, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema, functionName, niladic: true, arguments: null, builtIn: true, type, typeMapping) + : this(instance: null, schema, name, niladic: true, arguments: null, builtIn: true, type, typeMapping) { } // niladic public SqlFunctionExpression( SqlExpression instance, - string functionName, + string name, Type type, RelationalTypeMapping typeMapping) - : this(instance, schema: null, functionName, niladic: true, arguments: null, builtIn: true, type, typeMapping) + : this(instance, schema: null, name, niladic: true, arguments: null, builtIn: true, type, typeMapping) { } public SqlFunctionExpression( SqlExpression instance, - string functionName, + string name, IEnumerable arguments, Type type, RelationalTypeMapping typeMapping) - : this(instance, schema: null, functionName, niladic: false, arguments, builtIn: true, type, typeMapping) + : this(instance, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping) { } public SqlFunctionExpression( - string functionName, + string name, IEnumerable arguments, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema: null, functionName, niladic: false, arguments, builtIn: true, type, typeMapping) + : this(instance: null, schema: null, name, niladic: false, arguments, builtIn: true, type, typeMapping) { } public SqlFunctionExpression( string schema, - string functionName, + string name, IEnumerable arguments, Type type, RelationalTypeMapping typeMapping) - : this(instance: null, schema, functionName, niladic: false, arguments, builtIn: false, type, typeMapping) + : this(instance: null, schema, name, niladic: false, arguments, builtIn: false, type, typeMapping) { } private SqlFunctionExpression( Expression instance, string schema, - string functionName, + string name, bool niladic, IEnumerable arguments, bool builtIn, @@ -82,19 +81,19 @@ private SqlFunctionExpression( : base(type, typeMapping) { Instance = instance; - FunctionName = functionName; + Name = name; Schema = schema; IsNiladic = niladic; IsBuiltIn = builtIn; Arguments = (arguments ?? Array.Empty()).ToList(); } - public string FunctionName { get; } - public string Schema { get; } - public bool IsNiladic { get; } - public bool IsBuiltIn { get; } - public IReadOnlyList Arguments { get; } - public Expression Instance { get; } + public virtual string Name { get; } + public virtual string Schema { get; } + public virtual bool IsNiladic { get; } + public virtual bool IsBuiltIn { get; } + public virtual IReadOnlyList Arguments { get; } + public virtual Expression Instance { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { @@ -112,7 +111,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) ? new SqlFunctionExpression( instance, Schema, - FunctionName, + Name, IsNiladic, arguments, IsBuiltIn, @@ -121,20 +120,20 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) : this; } - public SqlFunctionExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) + public virtual SqlFunctionExpression ApplyTypeMapping(RelationalTypeMapping typeMapping) => new SqlFunctionExpression( Instance, Schema, - FunctionName, + Name, IsNiladic, Arguments, IsBuiltIn, Type, typeMapping ?? TypeMapping); - public SqlFunctionExpression Update(SqlExpression instance, IReadOnlyList arguments) + public virtual SqlFunctionExpression Update(SqlExpression instance, IReadOnlyList arguments) => instance != Instance || !arguments.SequenceEqual(Arguments) - ? new SqlFunctionExpression(instance, Schema, FunctionName, IsNiladic, arguments, IsBuiltIn, Type, TypeMapping) + ? new SqlFunctionExpression(instance, Schema, Name, IsNiladic, arguments, IsBuiltIn, Type, TypeMapping) : this; public override void Print(ExpressionPrinter expressionPrinter) @@ -144,7 +143,7 @@ public override void Print(ExpressionPrinter expressionPrinter) expressionPrinter.StringBuilder .Append(Schema) .Append(".") - .Append(FunctionName); + .Append(Name); } else { @@ -154,7 +153,7 @@ public override void Print(ExpressionPrinter expressionPrinter) expressionPrinter.StringBuilder.Append("."); } - expressionPrinter.StringBuilder.Append(FunctionName); + expressionPrinter.StringBuilder.Append(Name); } if (!IsNiladic) @@ -173,7 +172,7 @@ public override bool Equals(object obj) private bool Equals(SqlFunctionExpression sqlFunctionExpression) => base.Equals(sqlFunctionExpression) - && string.Equals(FunctionName, sqlFunctionExpression.FunctionName) + && string.Equals(Name, sqlFunctionExpression.Name) && string.Equals(Schema, sqlFunctionExpression.Schema) && ((Instance == null && sqlFunctionExpression.Instance == null) || (Instance != null && Instance.Equals(sqlFunctionExpression.Instance))) @@ -183,7 +182,7 @@ public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); - hash.Add(FunctionName); + hash.Add(Name); hash.Add(IsNiladic); hash.Add(Schema); hash.Add(Instance); diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlParameterExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs similarity index 92% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlParameterExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs index 2bb4b21557c..a08845f0052 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlParameterExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlParameterExpression.cs @@ -3,10 +3,9 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlParameterExpression : SqlExpression { diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlUnaryExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs similarity index 91% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlUnaryExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs index 05847209daa..11fa15657eb 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SqlUnaryExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlUnaryExpression.cs @@ -4,11 +4,10 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class SqlUnaryExpression : SqlExpression { @@ -37,13 +36,13 @@ public SqlUnaryExpression( Operand = operand; } - public ExpressionType OperatorType { get; } - public SqlExpression Operand { get; } + public virtual ExpressionType OperatorType { get; } + public virtual SqlExpression Operand { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) => Update((SqlExpression)visitor.Visit(Operand)); - public SqlUnaryExpression Update(SqlExpression operand) + public virtual SqlUnaryExpression Update(SqlExpression operand) => operand != Operand ? new SqlUnaryExpression(OperatorType, operand, Type, TypeMapping) : this; diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/TableExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs similarity index 74% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/TableExpression.cs rename to src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs index d21d4c9a6ce..09a813a9f6f 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/TableExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs @@ -3,16 +3,15 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public class TableExpression : TableExpressionBase { - internal TableExpression(string table, string schema, [NotNull] string alias) + internal TableExpression(string name, string schema, [NotNull] string alias) : base(alias) { - Table = table; + Name = name; Schema = schema; } @@ -26,18 +25,18 @@ public override void Print(ExpressionPrinter expressionPrinter) } expressionPrinter.StringBuilder - .Append(Table) + .Append(Name) .Append(" AS ") .Append(Alias); } - public string Table { get; } + public string Name { get; } public string Schema { get; } public override bool Equals(object obj) // This should be reference equal only. => obj != null && ReferenceEquals(this, obj); - public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Table, Schema); + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Name, Schema); } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/TableExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs similarity index 85% rename from src/EFCore.Relational/Query/Pipeline/SqlExpressions/TableExpressionBase.cs rename to src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs index 21bd6d7e114..cc31cf74d1f 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/TableExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs @@ -4,11 +4,9 @@ using System; using System.Linq.Expressions; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions { public abstract class TableExpressionBase : Expression, IPrintable { @@ -19,7 +17,7 @@ protected TableExpressionBase([CanBeNull] string alias) Alias = alias; } - public string Alias { get; internal set; } + public virtual string Alias { get; internal set; } protected override Expression VisitChildren(ExpressionVisitor visitor) => this; diff --git a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs index c0c3892a5af..81e7656c882 100644 --- a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs +++ b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorDependencies.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Scaffolding @@ -38,8 +39,14 @@ public sealed class ProviderCodeGeneratorDependencies /// 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. + /// /// - /// The plugins. + [EntityFrameworkInternal] public ProviderCodeGeneratorDependencies([NotNull] IEnumerable plugins) { Check.NotNull(plugins, nameof(plugins)); diff --git a/src/EFCore.Relational/Storage/ParameterNameGeneratorDependencies.cs b/src/EFCore.Relational/Storage/ParameterNameGeneratorDependencies.cs index 93046e7302b..12e534a430b 100644 --- a/src/EFCore.Relational/Storage/ParameterNameGeneratorDependencies.cs +++ b/src/EFCore.Relational/Storage/ParameterNameGeneratorDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Storage @@ -42,8 +43,14 @@ public sealed class ParameterNameGeneratorDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public ParameterNameGeneratorDependencies() { } diff --git a/src/EFCore.Relational/Storage/RelationalCommandBuilderDependencies.cs b/src/EFCore.Relational/Storage/RelationalCommandBuilderDependencies.cs index 6bc790f18e0..95b7be21658 100644 --- a/src/EFCore.Relational/Storage/RelationalCommandBuilderDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalCommandBuilderDependencies.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -43,8 +44,14 @@ public sealed class RelationalCommandBuilderDependencies /// 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. + /// /// - /// The source for s to use. + [EntityFrameworkInternal] public RelationalCommandBuilderDependencies( [NotNull] IRelationalTypeMappingSource typeMappingSource) { diff --git a/src/EFCore.Relational/Storage/RelationalConnectionDependencies.cs b/src/EFCore.Relational/Storage/RelationalConnectionDependencies.cs index 26224d84207..376f8d48dc9 100644 --- a/src/EFCore.Relational/Storage/RelationalConnectionDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalConnectionDependencies.cs @@ -47,13 +47,14 @@ public sealed class RelationalConnectionDependencies /// 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. + /// /// - /// The options for the current context instance. - /// The logger to which transaction messages will be written. - /// The logger to which connection messages will be written. - /// A service for resolving a connection string from a name. - /// A service for creating instances. - /// Contains the instance currently in use. + [EntityFrameworkInternal] public RelationalConnectionDependencies( [NotNull] IDbContextOptions contextOptions, [NotNull] IDiagnosticsLogger transactionLogger, diff --git a/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs b/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs index 54864741f9a..c26a35a0e13 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs @@ -54,16 +54,13 @@ public sealed class RelationalDatabaseCreatorDependencies /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// /// - /// The for the context this creator is being used with. - /// The to be used. - /// The to be used. - /// The to be used. - /// The to be used. - /// The to be used. - /// The to be used. - /// Contains the currently in use. - /// The command logger. [EntityFrameworkInternal] public RelationalDatabaseCreatorDependencies( [NotNull] IModel model, diff --git a/src/EFCore.Relational/Storage/RelationalDatabaseDependencies.cs b/src/EFCore.Relational/Storage/RelationalDatabaseDependencies.cs index dc8eb35aba6..64caac15161 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabaseDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabaseDependencies.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Update; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -45,10 +46,14 @@ public sealed class RelationalDatabaseDependencies /// 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. + /// /// - /// The to be used. - /// The to be used. - /// The to be used. + [EntityFrameworkInternal] public RelationalDatabaseDependencies( [NotNull] ICommandBatchPreparer batchPreparer, [NotNull] IBatchExecutor batchExecutor, diff --git a/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs index f37be7f9d5f..bf8989d2b0b 100644 --- a/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs +++ b/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs @@ -8,7 +8,7 @@ using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Microsoft.EntityFrameworkCore.Storage diff --git a/src/EFCore.Relational/Storage/RelationalSqlGenerationHelperDependencies.cs b/src/EFCore.Relational/Storage/RelationalSqlGenerationHelperDependencies.cs index 829023d44fe..7c226e6640c 100644 --- a/src/EFCore.Relational/Storage/RelationalSqlGenerationHelperDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalSqlGenerationHelperDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Storage @@ -42,8 +43,14 @@ public sealed class RelationalSqlGenerationHelperDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public RelationalSqlGenerationHelperDependencies() { } diff --git a/src/EFCore.Relational/Storage/RelationalTransactionFactoryDependencies.cs b/src/EFCore.Relational/Storage/RelationalTransactionFactoryDependencies.cs index b22f16bc3fd..f3d0dc2bb22 100644 --- a/src/EFCore.Relational/Storage/RelationalTransactionFactoryDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalTransactionFactoryDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Storage @@ -30,5 +31,28 @@ namespace Microsoft.EntityFrameworkCore.Storage /// public sealed class RelationalTransactionFactoryDependencies { + /// + /// + /// 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 RelationalTransactionFactoryDependencies() + { + } } } diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingSourceDependencies.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingSourceDependencies.cs index 786053ba8f6..792dbcde89c 100644 --- a/src/EFCore.Relational/Storage/RelationalTypeMappingSourceDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalTypeMappingSourceDependencies.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -45,8 +46,14 @@ public sealed class RelationalTypeMappingSourceDependencies /// 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. + /// /// - /// The plugins. + [EntityFrameworkInternal] public RelationalTypeMappingSourceDependencies( [NotNull] IEnumerable plugins) { diff --git a/src/EFCore.Relational/Storage/RelationalValueBufferFactoryDependencies.cs b/src/EFCore.Relational/Storage/RelationalValueBufferFactoryDependencies.cs index ff756fa3990..b81391aeb7f 100644 --- a/src/EFCore.Relational/Storage/RelationalValueBufferFactoryDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalValueBufferFactoryDependencies.cs @@ -51,9 +51,14 @@ public sealed class RelationalValueBufferFactoryDependencies /// 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. + /// /// - /// The type mapping source. - /// The core options. + [EntityFrameworkInternal] public RelationalValueBufferFactoryDependencies( [NotNull] IRelationalTypeMappingSource typeMappingSource, [NotNull] ICoreSingletonOptions coreOptions) diff --git a/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs b/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs index bb2f076c52c..4db455032cc 100644 --- a/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs +++ b/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs @@ -12,7 +12,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; diff --git a/src/EFCore.Relational/Update/Internal/CommandBatchPreparerDependencies.cs b/src/EFCore.Relational/Update/Internal/CommandBatchPreparerDependencies.cs index 688b4beb35a..e089b236c04 100644 --- a/src/EFCore.Relational/Update/Internal/CommandBatchPreparerDependencies.cs +++ b/src/EFCore.Relational/Update/Internal/CommandBatchPreparerDependencies.cs @@ -53,7 +53,14 @@ public sealed class CommandBatchPreparerDependencies /// 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 CommandBatchPreparerDependencies( [NotNull] IModificationCommandBatchFactory modificationCommandBatchFactory, [NotNull] IParameterNameGeneratorFactory parameterNameGeneratorFactory, diff --git a/src/EFCore.Relational/Update/ModificationCommandBatchFactoryDependencies.cs b/src/EFCore.Relational/Update/ModificationCommandBatchFactoryDependencies.cs index 1684b6b22d6..cdae4d57f57 100644 --- a/src/EFCore.Relational/Update/ModificationCommandBatchFactoryDependencies.cs +++ b/src/EFCore.Relational/Update/ModificationCommandBatchFactoryDependencies.cs @@ -47,13 +47,14 @@ public sealed class ModificationCommandBatchFactoryDependencies /// 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. + /// /// - /// The value buffer factory. - /// The command builder factory. - /// The sql generator. - /// The update generator. - /// Contains the currently in use. - /// A logger. + [EntityFrameworkInternal] public ModificationCommandBatchFactoryDependencies( [NotNull] IRelationalCommandBuilderFactory commandBuilderFactory, [NotNull] ISqlGenerationHelper sqlGenerationHelper, diff --git a/src/EFCore.Relational/Update/UpdateSqlGeneratorDependencies.cs b/src/EFCore.Relational/Update/UpdateSqlGeneratorDependencies.cs index abbe8297115..112aa2b3e60 100644 --- a/src/EFCore.Relational/Update/UpdateSqlGeneratorDependencies.cs +++ b/src/EFCore.Relational/Update/UpdateSqlGeneratorDependencies.cs @@ -52,9 +52,13 @@ public sealed class UpdateSqlGeneratorDependencies /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// /// - /// Helpers for generating update SQL. - /// The type mapping source. [EntityFrameworkInternal] public UpdateSqlGeneratorDependencies( [NotNull] ISqlGenerationHelper sqlGenerationHelper, diff --git a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs index ba6070c60de..12926a0d847 100644 --- a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs +++ b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs @@ -3,8 +3,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryCollectionMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs similarity index 77% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryCollectionMemberTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs index ad9f775a92b..ccaafa5f030 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs @@ -3,11 +3,11 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerGeometryCollectionMemberTranslator : IMemberTranslator { @@ -19,7 +19,7 @@ public SqlServerGeometryCollectionMemberTranslator(ISqlExpressionFactory sqlExpr _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (Equals(member, _count)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryCollectionMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs similarity index 83% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryCollectionMethodTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs index f64701d1b04..0e78b5d47f2 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerGeometryCollectionMethodTranslator : IMethodCallTranslator { @@ -24,7 +24,7 @@ public SqlServerGeometryCollectionMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _item)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs similarity index 95% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryMemberTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs index dec78343bb3..af132b5e9fe 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs @@ -5,12 +5,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerGeometryMemberTranslator : IMemberTranslator { @@ -49,7 +49,7 @@ public SqlServerGeometryMemberTranslator(IRelationalTypeMappingSource typeMappin _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (typeof(Geometry).IsAssignableFrom(member.DeclaringType)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs similarity index 96% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryMethodTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs index cb5a4954c11..7aa99ecc37e 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerGeometryMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs @@ -6,12 +6,12 @@ using System.Diagnostics; using System.Linq; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerGeometryMethodTranslator : IMethodCallTranslator { @@ -57,7 +57,7 @@ public SqlServerGeometryMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (typeof(Geometry).IsAssignableFrom(method.DeclaringType)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs similarity index 89% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerLineStringMemberTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs index 1daeb8b8d90..b6147b18c64 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs @@ -6,12 +6,12 @@ using System.Diagnostics; using System.Linq; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerLineStringMemberTranslator : IMemberTranslator { @@ -34,7 +34,7 @@ public SqlServerLineStringMemberTranslator(IRelationalTypeMappingSource typeMapp _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (_memberToFunctionName.TryGetValue(member, out var functionName)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerLineStringMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs similarity index 83% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerLineStringMethodTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs index 9c05c29b6ea..eaa8f1bf7b5 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerLineStringMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerLineStringMethodTranslator : IMethodCallTranslator { @@ -25,7 +25,7 @@ public SqlServerLineStringMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _getPointN)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerMultiLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs similarity index 77% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerMultiLineStringMemberTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs index 33f09d12b35..e0c9d706573 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerMultiLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs @@ -3,11 +3,11 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerMultiLineStringMemberTranslator : IMemberTranslator { @@ -19,7 +19,7 @@ public SqlServerMultiLineStringMemberTranslator(ISqlExpressionFactory sqlExpress _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (Equals(member, _isClosed)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs similarity index 96% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs index 6e062b6b3fb..c15313184fa 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs @@ -2,11 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// /// diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs similarity index 96% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs index 88ac0181a07..79885627dfc 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -2,11 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { /// /// diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPointMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs similarity index 92% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPointMemberTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs index 5b65f60a954..5f3b06dfda6 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPointMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPointMemberTranslator.cs @@ -5,11 +5,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { internal class SqlServerPointMemberTranslator : IMemberTranslator { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPolygonMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs similarity index 91% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPolygonMemberTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs index 519aa7acba5..598581c3864 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPolygonMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs @@ -5,12 +5,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerPolygonMemberTranslator : IMemberTranslator { @@ -33,7 +33,7 @@ public SqlServerPolygonMemberTranslator(IRelationalTypeMappingSource typeMapping _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (typeof(Polygon).IsAssignableFrom(member.DeclaringType)) { diff --git a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPolygonMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs similarity index 88% rename from src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPolygonMethodTranslator.cs rename to src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs index 30550fae33f..02335f66b92 100644 --- a/src/EFCore.SqlServer.NTS/Query/Pipeline/SqlServerPolygonMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs @@ -4,12 +4,12 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerPolygonMethodTranslator : IMethodCallTranslator { @@ -26,7 +26,7 @@ public SqlServerPolygonMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _getInteriorRingN)) { diff --git a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs index f684cd1514a..b0f34048ae9 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs @@ -9,14 +9,11 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; using Microsoft.EntityFrameworkCore.SqlServer.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Migrations.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; -using Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline; using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Update.Internal; using Microsoft.EntityFrameworkCore.SqlServer.ValueGeneration.Internal; diff --git a/src/EFCore.SqlServer/Query/Expressions/Internal/RowNumberExpression.cs b/src/EFCore.SqlServer/Query/Expressions/Internal/RowNumberExpression.cs deleted file mode 100644 index d25f9cd5614..00000000000 --- a/src/EFCore.SqlServer/Query/Expressions/Internal/RowNumberExpression.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; -using Microsoft.EntityFrameworkCore.Utilities; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Expressions.Internal -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public class RowNumberExpression : Expression - { - private readonly List _orderings = new List(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public RowNumberExpression([NotNull] IReadOnlyList orderings) - { - Check.NotNull(orderings, nameof(orderings)); - - _orderings.AddRange(orderings); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override ExpressionType NodeType => ExpressionType.Extension; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override bool CanReduce => false; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override Type Type => typeof(long); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual IReadOnlyList Orderings => _orderings; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected override Expression VisitChildren(ExpressionVisitor visitor) - { - var newOrderings = new List(); - var recreate = false; - foreach (var ordering in _orderings) - { - var newOrdering = new OrderingExpression( - (SqlExpression)visitor.Visit(ordering.Expression), - ordering.Ascending); - newOrderings.Add(newOrdering); - recreate |= newOrdering.Expression != ordering.Expression; - } - - return recreate ? new RowNumberExpression(newOrderings) : this; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override bool Equals(object obj) - { - if (obj is null) - { - return false; - } - - return ReferenceEquals(this, obj) ? true : obj.GetType() == GetType() && Equals((RowNumberExpression)obj); - } - - private bool Equals([NotNull] RowNumberExpression other) => _orderings.SequenceEqual(other._orderings); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override int GetHashCode() - { - var hash = new HashCode(); - foreach (var ordering in _orderings) - { - hash.Add(ordering); - } - return hash.ToHashCode(); - } - } -} diff --git a/src/EFCore.SqlServer/Query/Pipeline/SearchConditionConvertingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs similarity index 95% rename from src/EFCore.SqlServer/Query/Pipeline/SearchConditionConvertingExpressionVisitor.cs rename to src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs index 42006d9a172..34eab9c2287 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SearchConditionConvertingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SearchConditionConvertingExpressionVisitor : SqlExpressionVisitor { @@ -156,8 +156,8 @@ protected override Expression VisitSelect(SelectExpression selectExpression) } _isSearchCondition = true; - var havingExpression = (SqlExpression)Visit(selectExpression.HavingExpression); - changed |= havingExpression != selectExpression.HavingExpression; + var havingExpression = (SqlExpression)Visit(selectExpression.Having); + changed |= havingExpression != selectExpression.Having; var orderings = new List(); _isSearchCondition = false; @@ -276,8 +276,8 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction _isSearchCondition = parentSearchCondition; var newFunction = sqlFunctionExpression.Update(instance, arguments); - var condition = string.Equals(sqlFunctionExpression.FunctionName, "FREETEXT") - || string.Equals(sqlFunctionExpression.FunctionName, "CONTAINS"); + var condition = string.Equals(sqlFunctionExpression.Name, "FREETEXT") + || string.Equals(sqlFunctionExpression.Name, "CONTAINS"); return ApplyConversion(newFunction, condition); } @@ -340,13 +340,13 @@ protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpressio return leftJoinExpression.Update(table, joinPredicate); } - protected override Expression VisitSubSelect(SubSelectExpression subSelectExpression) + protected override Expression VisitSubSelect(ScalarSubqueryExpression scalarSubqueryExpression) { var parentSearchCondition = _isSearchCondition; - var subquery = (SelectExpression)Visit(subSelectExpression.Subquery); + var subquery = (SelectExpression)Visit(scalarSubqueryExpression.Subquery); _isSearchCondition = parentSearchCondition; - return ApplyConversion(subSelectExpression.Update(subquery), condition: false); + return ApplyConversion(scalarSubqueryExpression.Update(subquery), condition: false); } } } diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerConvertTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs similarity index 87% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerConvertTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs index 429e4599aec..ae80197094f 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerConvertTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerConvertTranslator.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerConvertTranslator : IMethodCallTranslator { @@ -50,7 +50,7 @@ public SqlServerConvertTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { return _supportedMethods.Contains(method) ? _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerDateDiffFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs similarity index 98% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerDateDiffFunctionsTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs index bf8cf0840ef..c385e075a3d 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerDateDiffFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateDiffFunctionsTranslator.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerDateDiffFunctionsTranslator : IMethodCallTranslator { @@ -311,7 +311,7 @@ public SqlServerDateDiffFunctionsTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_methodInfoDateDiffMapping.TryGetValue(method, out var datePart)) { diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerDateTimeMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs similarity index 92% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerDateTimeMemberTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs index 60d1a6d3c83..43bbadef99f 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerDateTimeMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerDateTimeMemberTranslator : IMemberTranslator { @@ -30,7 +30,7 @@ public SqlServerDateTimeMemberTranslator(ISqlExpressionFactory sqlExpressionFact _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { var declaringType = member.DeclaringType; diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerDateTimeMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs similarity index 91% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerDateTimeMethodTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs index 8e089f232c6..ac912eb4517 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerDateTimeMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMethodTranslator.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerDateTimeMethodTranslator : IMethodCallTranslator { @@ -36,7 +36,7 @@ public SqlServerDateTimeMethodTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_methodInfoDatePartMapping.TryGetValue(method, out var datePart)) { diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerFullTextSearchFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs similarity index 91% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerFullTextSearchFunctionsTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs index d7d0e96431f..d523978ba09 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerFullTextSearchFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerFullTextSearchFunctionsTranslator.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.SqlServer.Internal; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerFullTextSearchFunctionsTranslator : IMethodCallTranslator { @@ -51,7 +51,7 @@ public SqlServerFullTextSearchFunctionsTranslator( _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_functionMapping.TryGetValue(method, out var functionName)) { diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerIsDateFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs similarity index 73% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerIsDateFunctionTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs index a3b371d9cfd..c838f3ec8d7 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerIsDateFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerIsDateFunctionTranslator.cs @@ -3,12 +3,10 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; -using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; -using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerIsDateFunctionTranslator : IMethodCallTranslator { @@ -20,7 +18,7 @@ public class SqlServerIsDateFunctionTranslator : IMethodCallTranslator public SqlServerIsDateFunctionTranslator(ISqlExpressionFactory sqlExpressionFactory) => _sqlExpressionFactory = sqlExpressionFactory; - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { return _methodInfo.Equals(method) ? _sqlExpressionFactory.Convert( diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerMathTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs similarity index 95% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerMathTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs index 655c3124987..e14779ffca0 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerMathTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerMathTranslator : IMethodCallTranslator { @@ -67,7 +67,7 @@ public SqlServerMathTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_supportedMethodTranslations.TryGetValue(method, out var sqlFunctionName)) { diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerMemberTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMemberTranslatorProvider.cs similarity index 59% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerMemberTranslatorProvider.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerMemberTranslatorProvider.cs index f9f94b6658f..214ca6a2b49 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerMemberTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMemberTranslatorProvider.cs @@ -1,18 +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 System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerMemberTranslatorProvider : RelationalMemberTranslatorProvider { - public SqlServerMemberTranslatorProvider( - ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) - : base(sqlExpressionFactory, plugins) + public SqlServerMemberTranslatorProvider([NotNull] RelationalMemberTranslatorProviderDependencies dependencies) + : base(dependencies) { + var sqlExpressionFactory = dependencies.SqlExpressionFactory; + AddTranslators( new IMemberTranslator[] { new SqlServerDateTimeMemberTranslator(sqlExpressionFactory), diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerMethodCallTranslatorProvider.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs similarity index 73% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerMethodCallTranslatorProvider.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs index f27e23951f6..0e000fb5b76 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerMethodCallTranslatorProvider.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMethodCallTranslatorProvider.cs @@ -1,18 +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 System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerMethodCallTranslatorProvider : RelationalMethodCallTranslatorProvider { - public SqlServerMethodCallTranslatorProvider( - ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) - : base(sqlExpressionFactory, plugins) + public SqlServerMethodCallTranslatorProvider([NotNull] RelationalMethodCallTranslatorProviderDependencies dependencies) + : base(dependencies) { + var sqlExpressionFactory = dependencies.SqlExpressionFactory; + AddTranslators(new IMethodCallTranslator[] { new SqlServerConvertTranslator(sqlExpressionFactory), diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerNewGuidTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs similarity index 74% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerNewGuidTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs index 33403097083..2b6c7d648e1 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerNewGuidTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerNewGuidTranslator.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerNewGuidTranslator : IMethodCallTranslator { @@ -19,7 +19,7 @@ public SqlServerNewGuidTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { return _methodInfo.Equals(method) ? _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerObjectToStringTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs similarity index 87% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerObjectToStringTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs index 5dc295c7cfe..7a8cfeba23b 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerObjectToStringTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerObjectToStringTranslator.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerObjectToStringTranslator : IMethodCallTranslator { @@ -41,7 +41,7 @@ public SqlServerObjectToStringTranslator(ISqlExpressionFactory sqlExpressionFact _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { return method.Name == nameof(ToString) && arguments.Count == 0 diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerQuerySqlGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs similarity index 89% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerQuerySqlGenerator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs index 2cc0f5caaa4..1742cb823e1 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerQuerySqlGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs @@ -2,11 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerQuerySqlGenerator : QuerySqlGenerator { @@ -60,7 +60,7 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction { sqlFunctionExpression = new SqlFunctionExpression( schema: "dbo", - sqlFunctionExpression.FunctionName, + sqlFunctionExpression.Name, sqlFunctionExpression.Arguments, sqlFunctionExpression.Type, sqlFunctionExpression.TypeMapping); diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerQuerySqlGeneratorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs similarity index 71% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerQuerySqlGeneratorFactory.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs index 44efbb8cbd6..332c2c38393 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerQuerySqlGeneratorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGeneratorFactory.cs @@ -1,12 +1,12 @@ // 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.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { - public class SqlServerQuerySqlGeneratorFactory : QuerySqlGeneratorFactory + public class SqlServerQuerySqlGeneratorFactory : IQuerySqlGeneratorFactory { private readonly IRelationalCommandBuilderFactory _commandBuilderFactory; private readonly ISqlGenerationHelper _sqlGenerationHelper; @@ -14,13 +14,12 @@ public class SqlServerQuerySqlGeneratorFactory : QuerySqlGeneratorFactory public SqlServerQuerySqlGeneratorFactory( IRelationalCommandBuilderFactory commandBuilderFactory, ISqlGenerationHelper sqlGenerationHelper) - : base(commandBuilderFactory, sqlGenerationHelper) { _commandBuilderFactory = commandBuilderFactory; _sqlGenerationHelper = sqlGenerationHelper; } - public override QuerySqlGenerator Create() + public virtual QuerySqlGenerator Create() => new SqlServerQuerySqlGenerator(_commandBuilderFactory, _sqlGenerationHelper); } } diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerShapedQueryOptimizingExpressionVisitors.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerShapedQueryOptimizingExpressionVisitors.cs similarity index 83% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerShapedQueryOptimizingExpressionVisitors.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerShapedQueryOptimizingExpressionVisitors.cs index 909719ce6b9..33a1d8097a3 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerShapedQueryOptimizingExpressionVisitors.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerShapedQueryOptimizingExpressionVisitors.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerShapedQueryOptimizer : RelationalShapedQueryOptimizer { diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerShapedQueryOptimizingExpressionVisitorsFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerShapedQueryOptimizingExpressionVisitorsFactory.cs new file mode 100644 index 00000000000..7b0fb6b2ca0 --- /dev/null +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerShapedQueryOptimizingExpressionVisitorsFactory.cs @@ -0,0 +1,22 @@ +// 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.Query; + +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal +{ + public class SqlServerShapedQueryOptimizerFactory : IShapedQueryOptimizerFactory + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + + public SqlServerShapedQueryOptimizerFactory(ISqlExpressionFactory sqlExpressionFactory) + { + _sqlExpressionFactory = sqlExpressionFactory; + } + + public virtual ShapedQueryOptimizer Create(QueryCompilationContext queryCompilationContext) + { + return new SqlServerShapedQueryOptimizer(queryCompilationContext, _sqlExpressionFactory); + } + } +} diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerSqlTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs similarity index 91% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerSqlTranslatingExpressionVisitor.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs index e4301d4c9be..1ba2aeaffbb 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs @@ -4,11 +4,10 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerSqlTranslatingExpressionVisitor : RelationalSqlTranslatingExpressionVisitor { diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitorFactory.cs similarity index 78% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerSqlTranslatingExpressionVisitorFactory.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitorFactory.cs index 888d2d4ad75..a29038b7169 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitorFactory.cs @@ -2,12 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { - public class SqlServerSqlTranslatingExpressionVisitorFactory : RelationalSqlTranslatingExpressionVisitorFactory + public class SqlServerSqlTranslatingExpressionVisitorFactory : IRelationalSqlTranslatingExpressionVisitorFactory { private readonly ISqlExpressionFactory _sqlExpressionFactory; private readonly IMemberTranslatorProvider _memberTranslatorProvider; @@ -17,14 +16,13 @@ public SqlServerSqlTranslatingExpressionVisitorFactory( ISqlExpressionFactory sqlExpressionFactory, IMemberTranslatorProvider memberTranslatorProvider, IMethodCallTranslatorProvider methodCallTranslatorProvider) - : base(sqlExpressionFactory, memberTranslatorProvider, methodCallTranslatorProvider) { _sqlExpressionFactory = sqlExpressionFactory; _memberTranslatorProvider = memberTranslatorProvider; _methodCallTranslatorProvider = methodCallTranslatorProvider; } - public override RelationalSqlTranslatingExpressionVisitor Create( + public virtual RelationalSqlTranslatingExpressionVisitor Create( IModel model, QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) { diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerStringMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs similarity index 74% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerStringMemberTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs index e49524824ee..10f5688ff20 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerStringMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMemberTranslator.cs @@ -3,10 +3,10 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerStringMemberTranslator : IMemberTranslator { @@ -17,7 +17,7 @@ public SqlServerStringMemberTranslator(ISqlExpressionFactory sqlExpressionFactor _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (member.Name == nameof(string.Length) && instance?.Type == typeof(string)) diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs similarity index 97% rename from src/EFCore.SqlServer/Query/Pipeline/SqlServerStringMethodTranslator.cs rename to src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index 2c6a5347a46..016bc83e8e3 100644 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -6,10 +6,10 @@ using System.Linq; using System.Reflection; using System.Text; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal { public class SqlServerStringMethodTranslator : IMethodCallTranslator { @@ -57,7 +57,7 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_indexOfMethodInfo.Equals(method)) { diff --git a/src/EFCore.SqlServer/Query/Pipeline/SqlServerShapedQueryOptimizingExpressionVisitorsFactory.cs b/src/EFCore.SqlServer/Query/Pipeline/SqlServerShapedQueryOptimizingExpressionVisitorsFactory.cs deleted file mode 100644 index 79634821e76..00000000000 --- a/src/EFCore.SqlServer/Query/Pipeline/SqlServerShapedQueryOptimizingExpressionVisitorsFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -// 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.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Pipeline -{ - public class SqlServerShapedQueryOptimizerFactory : RelationalShapedQueryOptimizerFactory - { - public SqlServerShapedQueryOptimizerFactory(ISqlExpressionFactory sqlExpressionFactory) - : base(sqlExpressionFactory) - { - } - - public override ShapedQueryOptimizer Create(QueryCompilationContext queryCompilationContext) - { - return new SqlServerShapedQueryOptimizer(queryCompilationContext, SqlExpressionFactory); - } - } -} diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs index ac7976f7c5d..9651f4f846d 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs @@ -8,12 +8,12 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Sqlite.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.Sqlite.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Sqlite.Internal; using Microsoft.EntityFrameworkCore.Sqlite.Migrations.Internal; -using Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Sqlite.Query.Internal; using Microsoft.EntityFrameworkCore.Sqlite.Storage.Internal; using Microsoft.EntityFrameworkCore.Sqlite.Update.Internal; using Microsoft.EntityFrameworkCore.Storage; diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteDateTimeAddTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs similarity index 92% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteDateTimeAddTranslator.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs index 4313c75aaf7..ba51ac68053 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteDateTimeAddTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeAddTranslator.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteDateTimeAddTranslator : IMethodCallTranslator { @@ -33,7 +33,7 @@ public SqliteDateTimeAddTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { SqlExpression modifier = null; if (_addMilliseconds.Equals(method)) diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteDateTimeMemberTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs similarity index 94% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteDateTimeMemberTranslator.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs index f9b21e6fe40..cecf77073e5 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteDateTimeMemberTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteDateTimeMemberTranslator.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteDateTimeMemberTranslator : IMemberTranslator { @@ -32,7 +32,7 @@ public SqliteDateTimeMemberTranslator(ISqlExpressionFactory sqlExpressionFactory _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (member.DeclaringType == typeof(DateTime)) { diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteExpression.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs similarity index 88% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteExpression.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs index 0a7f1c633b6..9a3b6c9b3e4 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteExpression.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteExpression.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -36,13 +36,13 @@ public static SqlFunctionExpression Strftime( // If the inner call is another strftime then shortcut a double call if (timestring is SqlFunctionExpression rtrimFunction - && rtrimFunction.FunctionName == "rtrim" + && rtrimFunction.Name == "rtrim" && rtrimFunction.Arguments.Count == 2 && rtrimFunction.Arguments[0] is SqlFunctionExpression rtrimFunction2 - && rtrimFunction2.FunctionName == "rtrim" + && rtrimFunction2.Name == "rtrim" && rtrimFunction2.Arguments.Count == 2 && rtrimFunction2.Arguments[0] is SqlFunctionExpression strftimeFunction - && strftimeFunction.FunctionName == "strftime" + && strftimeFunction.Name == "strftime" && strftimeFunction.Arguments.Count > 1) { // Use its timestring parameter directly in place of ours diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMathTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs similarity index 93% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMathTranslator.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs index 86f545b9be7..c92e5a98ebb 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMathTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMathTranslator.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteMathTranslator : IMethodCallTranslator { @@ -49,7 +49,7 @@ public SqliteMathTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_supportedMethods.TryGetValue(method, out var sqlFunctionName)) { diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMemberTranslatorProvider.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs similarity index 59% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMemberTranslatorProvider.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs index 0a7b2d27efb..fd59fb9e924 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMemberTranslatorProvider.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMemberTranslatorProvider.cs @@ -1,18 +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 System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteMemberTranslatorProvider : RelationalMemberTranslatorProvider { - public SqliteMemberTranslatorProvider( - ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) - : base(sqlExpressionFactory, plugins) + public SqliteMemberTranslatorProvider(RelationalMemberTranslatorProviderDependencies dependencies) + : base(dependencies) { + var sqlExpressionFactory = dependencies.SqlExpressionFactory; + AddTranslators( new IMemberTranslator[] { diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMethodCallTranslatorProvider.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs similarity index 62% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMethodCallTranslatorProvider.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs index 3ad2e6a17b5..d1df98b017a 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteMethodCallTranslatorProvider.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs @@ -1,18 +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 System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteMethodCallTranslatorProvider : RelationalMethodCallTranslatorProvider { - public SqliteMethodCallTranslatorProvider( - ISqlExpressionFactory sqlExpressionFactory, - IEnumerable plugins) - : base(sqlExpressionFactory, plugins) + public SqliteMethodCallTranslatorProvider([NotNull] RelationalMethodCallTranslatorProviderDependencies dependencies) + : base(dependencies) { + var sqlExpressionFactory = dependencies.SqlExpressionFactory; + AddTranslators( new IMethodCallTranslator[] { diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteQuerySqlGenerator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs similarity index 91% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteQuerySqlGenerator.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs index de5cc6d9c27..e2baf00e439 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteQuerySqlGenerator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs @@ -3,12 +3,12 @@ using System; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteQuerySqlGenerator : QuerySqlGenerator { diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteQuerySqlGeneratorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs similarity index 71% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteQuerySqlGeneratorFactory.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs index f407f33d0c6..41fd0243719 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteQuerySqlGeneratorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGeneratorFactory.cs @@ -1,12 +1,12 @@ // 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.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { - public class SqliteQuerySqlGeneratorFactory : QuerySqlGeneratorFactory + public class SqliteQuerySqlGeneratorFactory : IQuerySqlGeneratorFactory { private readonly IRelationalCommandBuilderFactory _commandBuilderFactory; private readonly ISqlGenerationHelper _sqlGenerationHelper; @@ -14,13 +14,12 @@ public class SqliteQuerySqlGeneratorFactory : QuerySqlGeneratorFactory public SqliteQuerySqlGeneratorFactory( IRelationalCommandBuilderFactory commandBuilderFactory, ISqlGenerationHelper sqlGenerationHelper) - : base(commandBuilderFactory, sqlGenerationHelper) { _commandBuilderFactory = commandBuilderFactory; _sqlGenerationHelper = sqlGenerationHelper; } - public override QuerySqlGenerator Create() + public virtual QuerySqlGenerator Create() => new SqliteQuerySqlGenerator(_commandBuilderFactory, _sqlGenerationHelper); } } diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteSqlTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs similarity index 95% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteSqlTranslatingExpressionVisitor.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs index bbd8adbf084..854cd935e46 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs @@ -6,11 +6,10 @@ using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteSqlTranslatingExpressionVisitor : RelationalSqlTranslatingExpressionVisitor { diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteSqlTranslatingExpressionVisitorFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitorFactory.cs similarity index 78% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteSqlTranslatingExpressionVisitorFactory.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitorFactory.cs index e8cf8a625e4..1e96513d32f 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteSqlTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitorFactory.cs @@ -2,12 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { - public class SqliteSqlTranslatingExpressionVisitorFactory : RelationalSqlTranslatingExpressionVisitorFactory + public class SqliteSqlTranslatingExpressionVisitorFactory : IRelationalSqlTranslatingExpressionVisitorFactory { private readonly ISqlExpressionFactory _sqlExpressionFactory; private readonly IMemberTranslatorProvider _memberTranslatorProvider; @@ -17,14 +16,13 @@ public SqliteSqlTranslatingExpressionVisitorFactory( ISqlExpressionFactory sqlExpressionFactory, IMemberTranslatorProvider memberTranslatorProvider, IMethodCallTranslatorProvider methodCallTranslatorProvider) - : base(sqlExpressionFactory, memberTranslatorProvider, methodCallTranslatorProvider) { _sqlExpressionFactory = sqlExpressionFactory; _memberTranslatorProvider = memberTranslatorProvider; _methodCallTranslatorProvider = methodCallTranslatorProvider; } - public override RelationalSqlTranslatingExpressionVisitor Create( + public virtual RelationalSqlTranslatingExpressionVisitor Create( IModel model, QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor) { diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteStringLengthTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringLengthTranslator.cs similarity index 71% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteStringLengthTranslator.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteStringLengthTranslator.cs index 88493285006..0a4771739b3 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteStringLengthTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringLengthTranslator.cs @@ -3,10 +3,10 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteStringLengthTranslator : IMemberTranslator { @@ -17,7 +17,7 @@ public SqliteStringLengthTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { return instance.Type == typeof(string) && member.Name == nameof(string.Length) diff --git a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteStringMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs similarity index 97% rename from src/EFCore.Sqlite.Core/Query/Pipeline/SqliteStringMethodTranslator.cs rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs index b181f887447..5593a60a708 100644 --- a/src/EFCore.Sqlite.Core/Query/Pipeline/SqliteStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteStringMethodTranslator.cs @@ -6,10 +6,10 @@ using System.Linq; using System.Reflection; using System.Text; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteStringMethodTranslator : IMethodCallTranslator { @@ -64,7 +64,7 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_indexOfMethodInfo.Equals(method)) { diff --git a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs index f84ae12bfe4..a28a146046e 100644 --- a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs +++ b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs @@ -13,7 +13,6 @@ using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Scaffolding; using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; diff --git a/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs b/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs index 64011ac7006..25353c90531 100644 --- a/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs +++ b/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs @@ -3,8 +3,8 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Sqlite.Query.Internal; using Microsoft.EntityFrameworkCore.Sqlite.Storage.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryCollectionMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs similarity index 75% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryCollectionMemberTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs index 38a8ea2a93e..84483db0c52 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs @@ -3,11 +3,11 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteGeometryCollectionMemberTranslator : IMemberTranslator { @@ -19,7 +19,7 @@ public SqliteGeometryCollectionMemberTranslator(ISqlExpressionFactory sqlExpress _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { return Equals(member, _count) ? _sqlExpressionFactory.Function("NumGeometries", new[] { instance }, returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryCollectionMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs similarity index 79% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryCollectionMethodTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs index 356c4e9ee14..0bf492f0590 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMethodTranslator.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteGeometryCollectionMethodTranslator : IMethodCallTranslator { @@ -19,7 +19,7 @@ public SqliteGeometryCollectionMethodTranslator(ISqlExpressionFactory sqlExpress _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _item)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs similarity index 95% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryMemberTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs index 53ba1c9a838..21a28872170 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteGeometryMemberTranslator : IMemberTranslator { @@ -39,7 +39,7 @@ public SqliteGeometryMemberTranslator(ISqlExpressionFactory sqlExpressionFactory _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (_memberToFunctionName.TryGetValue(member, out var functionName)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs similarity index 94% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryMethodTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs index 788ec7abd4d..c442876f6b4 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteGeometryMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs @@ -5,11 +5,11 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteGeometryMethodTranslator : IMethodCallTranslator { @@ -52,7 +52,7 @@ public SqliteGeometryMethodTranslator(ISqlExpressionFactory sqlExpressionFactory _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (_methodToFunctionName.TryGetValue(method, out var functionName)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs similarity index 87% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteLineStringMemberTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs index 1ab762cf1fa..c2508f2359a 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteLineStringMemberTranslator : IMemberTranslator { @@ -29,7 +29,7 @@ public SqliteLineStringMemberTranslator(ISqlExpressionFactory sqlExpressionFacto _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (_memberToFunctionName.TryGetValue(member, out var functionName)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteLineStringMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs similarity index 79% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteLineStringMethodTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs index b92b5cbe950..3154ea9d6f5 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteLineStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteLineStringMethodTranslator : IMethodCallTranslator { @@ -20,7 +20,7 @@ public SqliteLineStringMethodTranslator(ISqlExpressionFactory sqlExpressionFacto _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _getPointN)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteMultiLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs similarity index 80% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteMultiLineStringMemberTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs index 021dc4922b9..b312922bd2b 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteMultiLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs @@ -3,11 +3,11 @@ using System; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqliteMultiLineStringMemberTranslator : IMemberTranslator { @@ -19,7 +19,7 @@ public SqliteMultiLineStringMemberTranslator(ISqlExpressionFactory sqlExpression _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { if (Equals(member, _isClosed)) { diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs similarity index 95% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteNetTopologySuiteMemberTranslatorPlugin.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs index 7e24ed61ddc..0f70a8deabd 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// /// diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs similarity index 95% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs index 7e5b54cad96..0937c85dbba 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { /// /// diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePointMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs similarity index 80% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePointMemberTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs index a57ef0a420c..9f3fde801fc 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePointMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqlitePointMemberTranslator : IMemberTranslator { @@ -26,7 +26,7 @@ public SqlitePointMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { return _memberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function(functionName, new[] { instance }, returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePolygonMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs similarity index 79% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePolygonMemberTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs index efeb79020de..0c712257629 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePolygonMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqlitePolygonMemberTranslator : IMemberTranslator { @@ -25,7 +25,7 @@ public SqlitePolygonMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) + public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType) { return _memberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function(functionName, new[] { instance }, returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePolygonMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs similarity index 79% rename from src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePolygonMethodTranslator.cs rename to src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs index 8e55458ee82..49012d6ff5b 100644 --- a/src/EFCore.Sqlite.NTS/Query/Pipeline/SqlitePolygonMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; using System.Reflection; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using NetTopologySuite.Geometries; -namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal { public class SqlitePolygonMethodTranslator : IMethodCallTranslator { @@ -21,7 +21,7 @@ public SqlitePolygonMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory = sqlExpressionFactory; } - public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) { if (Equals(method, _getInteriorRingN)) { diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs index de0492883a2..1a14c9ade6b 100644 --- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs @@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { diff --git a/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.cs b/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.cs index ea0c63972b4..6751d235fa7 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.cs @@ -55,7 +55,14 @@ public sealed class StateManagerDependencies /// 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 StateManagerDependencies( [NotNull] IInternalEntityEntryFactory internalEntityEntryFactory, [NotNull] IInternalEntityEntrySubscriber internalEntityEntrySubscriber, diff --git a/src/EFCore/ChangeTracking/ValueComparer.cs b/src/EFCore/ChangeTracking/ValueComparer.cs index ef05364e3c6..8b02883736c 100644 --- a/src/EFCore/ChangeTracking/ValueComparer.cs +++ b/src/EFCore/ChangeTracking/ValueComparer.cs @@ -7,7 +7,7 @@ using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.ChangeTracking @@ -133,10 +133,14 @@ public virtual Expression ExtractEqualsBody( Check.NotNull(leftExpression, nameof(leftExpression)); Check.NotNull(rightExpression, nameof(rightExpression)); - return ReplacingExpressionVisitor.Replace( - EqualsExpression.Parameters[0], leftExpression, - EqualsExpression.Parameters[1], rightExpression, - EqualsExpression.Body); + var original1 = EqualsExpression.Parameters[0]; + var original2 = EqualsExpression.Parameters[1]; + + return new ReplacingExpressionVisitor( + new Dictionary { + { original1, leftExpression }, + { original2, rightExpression } + }).Visit(EqualsExpression.Body); } /// diff --git a/src/EFCore/DbSet.cs b/src/EFCore/DbSet.cs index 34083e9d7bb..77d290824eb 100644 --- a/src/EFCore/DbSet.cs +++ b/src/EFCore/DbSet.cs @@ -13,7 +13,6 @@ using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query.Internal; namespace Microsoft.EntityFrameworkCore { diff --git a/src/EFCore/Diagnostics/CoreLoggerExtensions.cs b/src/EFCore/Diagnostics/CoreLoggerExtensions.cs index 4424cf85ce0..1351b6639a4 100644 --- a/src/EFCore/Diagnostics/CoreLoggerExtensions.cs +++ b/src/EFCore/Diagnostics/CoreLoggerExtensions.cs @@ -16,7 +16,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Update; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/QueryExpressionEventData.cs b/src/EFCore/Diagnostics/QueryExpressionEventData.cs index d5a272dd0c5..e1a4d46bbac 100644 --- a/src/EFCore/Diagnostics/QueryExpressionEventData.cs +++ b/src/EFCore/Diagnostics/QueryExpressionEventData.cs @@ -5,7 +5,7 @@ using System.Diagnostics; using System.Linq.Expressions; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Diagnostics { diff --git a/src/EFCore/EF.CompileAsyncQuery.cs b/src/EFCore/EF.CompileAsyncQuery.cs index 2af88eef194..6993cc03482 100644 --- a/src/EFCore/EF.CompileAsyncQuery.cs +++ b/src/EFCore/EF.CompileAsyncQuery.cs @@ -8,7 +8,6 @@ using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Internal; namespace Microsoft.EntityFrameworkCore diff --git a/src/EFCore/Extensions/EntityTypeExtensions.cs b/src/EFCore/Extensions/EntityTypeExtensions.cs index 3a99e9dd666..7f6a0e92ff6 100644 --- a/src/EFCore/Extensions/EntityTypeExtensions.cs +++ b/src/EFCore/Extensions/EntityTypeExtensions.cs @@ -22,6 +22,9 @@ namespace Microsoft.EntityFrameworkCore /// public static class EntityTypeExtensions { + public static IEnumerable GetConcreteDerivedTypesInclusive([NotNull] this IEntityType entityType) + => entityType.GetDerivedTypesInclusive().Where(et => !et.IsAbstract()); + /// /// Checks if this entity type represents an abstract type. /// diff --git a/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs b/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs index 12d29566e18..24757de428f 100644 --- a/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs +++ b/src/EFCore/Extensions/Internal/EFPropertyExtensions.cs @@ -22,54 +22,6 @@ namespace Microsoft.EntityFrameworkCore.Internal // ReSharper disable once InconsistentNaming public static class EFPropertyExtensions { - private static readonly string _efTypeName = typeof(EF).FullName; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static bool TryGetEFPropertyArguments( - [NotNull] this MethodCallExpression methodCallExpression, - out Expression entityExpression, - out string propertyName) - { - if (IsEFProperty(methodCallExpression) - && methodCallExpression.Arguments[1] is ConstantExpression propertyNameExpression) - { - entityExpression = methodCallExpression.Arguments[0]; - propertyName = (string)propertyNameExpression.Value; - return true; - } - - (entityExpression, propertyName) = (null, null); - return false; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static bool IsEFProperty([NotNull] this MethodCallExpression methodCallExpression) - => IsEFPropertyMethod(methodCallExpression.Method); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public 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; - /// /// 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 diff --git a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs index fd8823db083..dc2090e61d8 100644 --- a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs +++ b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs @@ -7,15 +7,11 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Runtime.Versioning; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; using Microsoft.EntityFrameworkCore.Utilities; // ReSharper disable once CheckNamespace @@ -40,50 +36,6 @@ public static bool IsNullConstantExpression([NotNull] this Expression expression => expression.RemoveConvert() is ConstantExpression constantExpression && constantExpression.Value == null; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static PropertyInfo GetPropertyAccess([NotNull] this LambdaExpression propertyAccessExpression) - { - Debug.Assert(propertyAccessExpression.Parameters.Count == 1); - - var parameterExpression = propertyAccessExpression.Parameters.Single(); - var propertyInfo = parameterExpression.MatchSimplePropertyAccess(propertyAccessExpression.Body); - - if (propertyInfo == null) - { - throw new ArgumentException( - CoreStrings.InvalidPropertyExpression(propertyAccessExpression), - nameof(propertyAccessExpression)); - } - - var declaringType = propertyInfo.DeclaringType; - var parameterType = parameterExpression.Type; - - if (declaringType != null - && declaringType != parameterType - && declaringType.GetTypeInfo().IsInterface - && declaringType.GetTypeInfo().IsAssignableFrom(parameterType.GetTypeInfo())) - { - var propertyGetter = propertyInfo.GetMethod; - var interfaceMapping = parameterType.GetTypeInfo().GetRuntimeInterfaceMap(declaringType); - var index = Array.FindIndex(interfaceMapping.InterfaceMethods, p => propertyGetter.Equals(p)); - var targetMethod = interfaceMapping.TargetMethods[index]; - foreach (var runtimeProperty in parameterType.GetRuntimeProperties()) - { - if (targetMethod.Equals(runtimeProperty.GetMethod)) - { - return runtimeProperty; - } - } - } - - return propertyInfo; - } - /// /// 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 @@ -255,26 +207,6 @@ public static bool IsEntityQueryable([NotNull] this ConstantExpression constantE => constantExpression.Type.GetTypeInfo().IsGenericType && constantExpression.Type.GetGenericTypeDefinition() == typeof(EntityQueryable<>); - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static Expression CreateAssignExpression( - [NotNull] this MemberExpression left, - [NotNull] Expression right) - { - var leftType = left.Type; - if (leftType != right.Type - && right.Type.GetTypeInfo().IsAssignableFrom(leftType.GetTypeInfo())) - { - right = Expression.Convert(right, leftType); - } - - return left.Assign(right); - } - /// /// 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 diff --git a/src/EFCore/Extensions/Internal/TypeExtensions.cs b/src/EFCore/Extensions/Internal/TypeExtensions.cs index f4b24e93679..9e0e50de72b 100644 --- a/src/EFCore/Extensions/Internal/TypeExtensions.cs +++ b/src/EFCore/Extensions/Internal/TypeExtensions.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Text; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query; // ReSharper disable once CheckNamespace namespace Microsoft.EntityFrameworkCore.Internal diff --git a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs index 98df6e952f4..eedca6b9915 100644 --- a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs +++ b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs @@ -17,7 +17,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -281,6 +280,7 @@ public virtual EntityFrameworkServicesBuilder TryAddCoreServices() .AddDependencySingleton() .AddDependencySingleton() .AddDependencySingleton() + .AddDependencySingleton() .AddDependencyScoped() .AddDependencyScoped() .AddDependencyScoped() diff --git a/src/EFCore/Infrastructure/ExpressionExtensions.cs b/src/EFCore/Infrastructure/ExpressionExtensions.cs index 232879b67cf..b23404cf3a9 100644 --- a/src/EFCore/Infrastructure/ExpressionExtensions.cs +++ b/src/EFCore/Infrastructure/ExpressionExtensions.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; @@ -23,6 +25,88 @@ 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); + + public static bool TryGetEFPropertyArguments( + [NotNull] this MethodCallExpression methodCallExpression, + out Expression entityExpression, + out string propertyName) + { + if (IsEFProperty(methodCallExpression) + && methodCallExpression.Arguments[1] is ConstantExpression propertyNameExpression) + { + entityExpression = methodCallExpression.Arguments[0]; + propertyName = (string)propertyNameExpression.Value; + return true; + } + + (entityExpression, propertyName) = (null, null); + return false; + } + + public static Expression CreateAssignExpression( + [NotNull] this MemberExpression left, + [NotNull] Expression right) + { + var leftType = left.Type; + if (leftType != right.Type + && right.Type.GetTypeInfo().IsAssignableFrom(leftType.GetTypeInfo())) + { + right = Expression.Convert(right, leftType); + } + + return left.Assign(right); + } + + public static PropertyInfo GetPropertyAccess([NotNull] this LambdaExpression propertyAccessExpression) + { + Debug.Assert(propertyAccessExpression.Parameters.Count == 1); + + var parameterExpression = propertyAccessExpression.Parameters.Single(); + var propertyInfo = parameterExpression.MatchSimplePropertyAccess(propertyAccessExpression.Body); + + if (propertyInfo == null) + { + throw new ArgumentException( + CoreStrings.InvalidPropertyExpression(propertyAccessExpression), + nameof(propertyAccessExpression)); + } + + var declaringType = propertyInfo.DeclaringType; + var parameterType = parameterExpression.Type; + + if (declaringType != null + && declaringType != parameterType + && declaringType.GetTypeInfo().IsInterface + && declaringType.GetTypeInfo().IsAssignableFrom(parameterType.GetTypeInfo())) + { + var propertyGetter = propertyInfo.GetMethod; + var interfaceMapping = parameterType.GetTypeInfo().GetRuntimeInterfaceMap(declaringType); + var index = Array.FindIndex(interfaceMapping.InterfaceMethods, p => propertyGetter.Equals(p)); + var targetMethod = interfaceMapping.TargetMethods[index]; + foreach (var runtimeProperty in parameterType.GetRuntimeProperties()) + { + if (targetMethod.Equals(runtimeProperty.GetMethod)) + { + return runtimeProperty; + } + } + } + + return propertyInfo; + } + /// /// /// Returns a list of extracted from the given simple diff --git a/src/EFCore/Infrastructure/ModelCacheKeyFactoryDependencies.cs b/src/EFCore/Infrastructure/ModelCacheKeyFactoryDependencies.cs index 78a3aa08b1a..879dd5e96e2 100644 --- a/src/EFCore/Infrastructure/ModelCacheKeyFactoryDependencies.cs +++ b/src/EFCore/Infrastructure/ModelCacheKeyFactoryDependencies.cs @@ -42,8 +42,14 @@ public sealed class ModelCacheKeyFactoryDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public ModelCacheKeyFactoryDependencies() { } diff --git a/src/EFCore/Infrastructure/ModelCustomizerDependencies.cs b/src/EFCore/Infrastructure/ModelCustomizerDependencies.cs index c237f63a4ff..22a978a84bf 100644 --- a/src/EFCore/Infrastructure/ModelCustomizerDependencies.cs +++ b/src/EFCore/Infrastructure/ModelCustomizerDependencies.cs @@ -45,7 +45,14 @@ public sealed class ModelCustomizerDependencies /// 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 ModelCustomizerDependencies([NotNull] IDbSetFinder setFinder) { Check.NotNull(setFinder, nameof(setFinder)); diff --git a/src/EFCore/Infrastructure/ModelValidatorDependencies.cs b/src/EFCore/Infrastructure/ModelValidatorDependencies.cs index 2624560c403..a6e7197bec7 100644 --- a/src/EFCore/Infrastructure/ModelValidatorDependencies.cs +++ b/src/EFCore/Infrastructure/ModelValidatorDependencies.cs @@ -50,9 +50,14 @@ public sealed class ModelValidatorDependencies /// 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. + /// /// - /// The type mapper. - /// The member classifier. + [EntityFrameworkInternal] public ModelValidatorDependencies( [NotNull] ITypeMappingSource typeMappingSource, [NotNull] IMemberClassifier memberClassifier) diff --git a/src/EFCore/Infrastructure/ProductInfo.cs b/src/EFCore/Infrastructure/ProductInfo.cs new file mode 100644 index 00000000000..c38d1eecdd3 --- /dev/null +++ b/src/EFCore/Infrastructure/ProductInfo.cs @@ -0,0 +1,14 @@ +// 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; + +namespace Microsoft.EntityFrameworkCore.Infrastructure +{ + public static class ProductInfo + { + public static string GetVersion() + => typeof(ProductInfo).GetTypeInfo().Assembly + .GetCustomAttribute().InformationalVersion; + } +} diff --git a/src/EFCore/Internal/ProductInfo.cs b/src/EFCore/Internal/ProductInfo.cs deleted file mode 100644 index 54e75998188..00000000000 --- a/src/EFCore/Internal/ProductInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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; - -namespace Microsoft.EntityFrameworkCore.Internal -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static class ProductInfo - { - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static string GetVersion() - => typeof(ProductInfo).GetTypeInfo().Assembly - .GetCustomAttribute().InformationalVersion; - } -} diff --git a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilderDependencies.cs b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilderDependencies.cs index 692de6fc687..a5f04833249 100644 --- a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilderDependencies.cs +++ b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilderDependencies.cs @@ -64,16 +64,14 @@ public sealed class ProviderConventionSetBuilderDependencies /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// /// - /// The type mapping source. - /// The constructor binding factory. - /// The parameter binding factories. - /// The member classifier. - /// The model logger. - /// The model validation logger. - /// The set finder. - /// The current context instance. - /// The model validator. + [EntityFrameworkInternal] public ProviderConventionSetBuilderDependencies( [NotNull] ITypeMappingSource typeMappingSource, [NotNull] IConstructorBindingFactory constructorBindingFactory, diff --git a/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs index 99c5574084f..7b9912b9332 100644 --- a/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs @@ -8,10 +8,10 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { diff --git a/src/EFCore/Metadata/CoreAnnotationNames.cs b/src/EFCore/Metadata/CoreAnnotationNames.cs new file mode 100644 index 00000000000..b5d38dfb004 --- /dev/null +++ b/src/EFCore/Metadata/CoreAnnotationNames.cs @@ -0,0 +1,92 @@ +// 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.Collections.Generic; + +namespace Microsoft.EntityFrameworkCore.Metadata +{ + public static class CoreAnnotationNames + { + public const string MaxLength = "MaxLength"; + + public const string Unicode = "Unicode"; + + public const string ProductVersion = "ProductVersion"; + + public const string ValueGeneratorFactory = "ValueGeneratorFactory"; + + public const string PropertyAccessMode = "PropertyAccessMode"; + + public const string NavigationAccessMode = "NavigationAccessMode"; + + public const string ChangeTrackingStrategy = "ChangeTrackingStrategy"; + + public const string OwnedTypes = "OwnedTypes"; + + public const string DiscriminatorProperty = "DiscriminatorProperty"; + + public const string DiscriminatorValue = "DiscriminatorValue"; + + public const string ConstructorBinding = "ConstructorBinding"; + + public const string TypeMapping = "TypeMapping"; + + public const string ValueConverter = "ValueConverter"; + + public const string ValueComparer = "ValueComparer"; + + public const string KeyValueComparer = "KeyValueComparer"; + + public const string StructuralValueComparer = "StructuralValueComparer"; + + public const string AfterSaveBehavior = "AfterSaveBehavior"; + + public const string BeforeSaveBehavior = "BeforeSaveBehavior"; + + public const string QueryFilter = "QueryFilter"; + + public const string DefiningQuery = "DefiningQuery"; + + public const string EagerLoaded = "EagerLoaded"; + + public const string ProviderClrType = "ProviderClrType"; + + public const string InverseNavigations = "InversePropertyAttributeConvention:InverseNavigations"; + + public const string NavigationCandidates = "RelationshipDiscoveryConvention:NavigationCandidates"; + + public const string AmbiguousNavigations = "RelationshipDiscoveryConvention:AmbiguousNavigations"; + + public const string DuplicateServiceProperties = "ServicePropertyDiscoveryConvention:DuplicateServiceProperties"; + + public static readonly ISet AllNames = new HashSet + { + MaxLength, + Unicode, + ProductVersion, + ValueGeneratorFactory, + PropertyAccessMode, + NavigationAccessMode, + ChangeTrackingStrategy, + OwnedTypes, + DiscriminatorProperty, + DiscriminatorValue, + ConstructorBinding, + TypeMapping, + ValueConverter, + ValueComparer, + KeyValueComparer, + StructuralValueComparer, + AfterSaveBehavior, + BeforeSaveBehavior, + QueryFilter, + DefiningQuery, + EagerLoaded, + ProviderClrType, + InverseNavigations, + NavigationCandidates, + AmbiguousNavigations, + DuplicateServiceProperties + }; + } +} diff --git a/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs b/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs deleted file mode 100644 index 1b8eb0980a4..00000000000 --- a/src/EFCore/Metadata/Internal/CoreAnnotationNames.cs +++ /dev/null @@ -1,260 +0,0 @@ -// 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.Collections.Generic; - -namespace Microsoft.EntityFrameworkCore.Metadata.Internal -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static class CoreAnnotationNames - { - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string MaxLength = "MaxLength"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string Unicode = "Unicode"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string ProductVersion = "ProductVersion"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string ValueGeneratorFactory = "ValueGeneratorFactory"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string PropertyAccessMode = "PropertyAccessMode"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string NavigationAccessMode = "NavigationAccessMode"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string ChangeTrackingStrategy = "ChangeTrackingStrategy"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string OwnedTypes = "OwnedTypes"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string DiscriminatorProperty = "DiscriminatorProperty"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string DiscriminatorValue = "DiscriminatorValue"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string ConstructorBinding = "ConstructorBinding"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string TypeMapping = "TypeMapping"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string ValueConverter = "ValueConverter"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string ValueComparer = "ValueComparer"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string KeyValueComparer = "KeyValueComparer"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string StructuralValueComparer = "StructuralValueComparer"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string AfterSaveBehavior = "AfterSaveBehavior"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string BeforeSaveBehavior = "BeforeSaveBehavior"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string QueryFilter = "QueryFilter"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string DefiningQuery = "DefiningQuery"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string EagerLoaded = "EagerLoaded"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string ProviderClrType = "ProviderClrType"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string InverseNavigations = "InversePropertyAttributeConvention:InverseNavigations"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string NavigationCandidates = "RelationshipDiscoveryConvention:NavigationCandidates"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string AmbiguousNavigations = "RelationshipDiscoveryConvention:AmbiguousNavigations"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public const string DuplicateServiceProperties = "ServicePropertyDiscoveryConvention:DuplicateServiceProperties"; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static readonly ISet AllNames = new HashSet - { - MaxLength, - Unicode, - ProductVersion, - ValueGeneratorFactory, - PropertyAccessMode, - NavigationAccessMode, - ChangeTrackingStrategy, - OwnedTypes, - DiscriminatorProperty, - DiscriminatorValue, - ConstructorBinding, - TypeMapping, - ValueConverter, - ValueComparer, - KeyValueComparer, - StructuralValueComparer, - AfterSaveBehavior, - BeforeSaveBehavior, - QueryFilter, - DefiningQuery, - EagerLoaded, - ProviderClrType, - InverseNavigations, - NavigationCandidates, - AmbiguousNavigations, - DuplicateServiceProperties - }; - } -} diff --git a/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs b/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs index 13a44b5ec9f..dcabc49c3d3 100644 --- a/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs +++ b/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs @@ -375,15 +375,6 @@ public static PropertyCounts CalculateCounts([NotNull] this EntityType entityTyp public static Func GetEmptyShadowValuesFactory([NotNull] this IEntityType entityType) => entityType.AsEntityType().EmptyShadowValuesFactory; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static IEnumerable GetConcreteDerivedTypesInclusive([NotNull] this IEntityType entityType) - => entityType.GetDerivedTypesInclusive().Where(et => !et.IsAbstract()); - /// /// 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 diff --git a/src/EFCore/Metadata/Internal/PropertyIdentity.cs b/src/EFCore/Metadata/Internal/PropertyIdentity.cs deleted file mode 100644 index 4d9389be054..00000000000 --- a/src/EFCore/Metadata/Internal/PropertyIdentity.cs +++ /dev/null @@ -1,123 +0,0 @@ -// 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.Diagnostics; -using System.Reflection; -using JetBrains.Annotations; - -namespace Microsoft.EntityFrameworkCore.Metadata.Internal -{ - /// - /// 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. - /// - [DebuggerDisplay("{DebuggerDisplay(),nq}")] - public readonly struct MemberIdentity - { - private readonly object _nameOrMember; - - /// - /// 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. - /// - [DebuggerStepThrough] - public MemberIdentity([NotNull] string name) - : this((object)name) - { - } - - /// - /// 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. - /// - [DebuggerStepThrough] - public MemberIdentity([NotNull] MemberInfo memberInfo) - : this((object)memberInfo) - { - } - - [DebuggerStepThrough] - private MemberIdentity([CanBeNull] object nameOrMember) - { - _nameOrMember = nameOrMember; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public bool IsNone() => _nameOrMember == null; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static readonly MemberIdentity None = new MemberIdentity((object)null); - - /// - /// 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. - /// - [DebuggerStepThrough] - public static MemberIdentity Create([CanBeNull] string name) - => name == null ? None : new MemberIdentity(name); - - /// - /// 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. - /// - [DebuggerStepThrough] - public static MemberIdentity Create([CanBeNull] MemberInfo property) - => property == null ? None : new MemberIdentity(property); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static MemberIdentity Create([CanBeNull] Navigation navigation) - => navigation?.GetIdentifyingMemberInfo() == null - ? Create(navigation?.Name) - : Create(navigation.GetIdentifyingMemberInfo()); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public string Name - { - [DebuggerStepThrough] get => MemberInfo?.GetSimpleMemberName() ?? (string)_nameOrMember; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public MemberInfo MemberInfo - { - [DebuggerStepThrough] get => _nameOrMember as MemberInfo; - } - - private string DebuggerDisplay() - => Name ?? "NONE"; - } -} diff --git a/src/EFCore/Metadata/LazyLoaderParameterBindingFactoryDependencies.cs b/src/EFCore/Metadata/LazyLoaderParameterBindingFactoryDependencies.cs index 60941cb861f..76a5a2ccd78 100644 --- a/src/EFCore/Metadata/LazyLoaderParameterBindingFactoryDependencies.cs +++ b/src/EFCore/Metadata/LazyLoaderParameterBindingFactoryDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Metadata @@ -42,7 +43,14 @@ public sealed class LazyLoaderParameterBindingFactoryDependencies /// 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 LazyLoaderParameterBindingFactoryDependencies() { } diff --git a/src/EFCore/Metadata/PropertyIdentity.cs b/src/EFCore/Metadata/PropertyIdentity.cs new file mode 100644 index 00000000000..d970b412afc --- /dev/null +++ b/src/EFCore/Metadata/PropertyIdentity.cs @@ -0,0 +1,64 @@ +// 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.Diagnostics; +using System.Reflection; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + +namespace Microsoft.EntityFrameworkCore.Metadata +{ + [DebuggerDisplay("{DebuggerDisplay(),nq}")] + public readonly struct MemberIdentity + { + private readonly object _nameOrMember; + + [DebuggerStepThrough] + public MemberIdentity([NotNull] string name) + : this((object)name) + { + } + + [DebuggerStepThrough] + public MemberIdentity([NotNull] MemberInfo memberInfo) + : this((object)memberInfo) + { + } + + [DebuggerStepThrough] + private MemberIdentity([CanBeNull] object nameOrMember) + { + _nameOrMember = nameOrMember; + } + + public bool IsNone() => _nameOrMember == null; + + public static readonly MemberIdentity None = new MemberIdentity((object)null); + + [DebuggerStepThrough] + public static MemberIdentity Create([CanBeNull] string name) + => name == null ? None : new MemberIdentity(name); + + [DebuggerStepThrough] + public static MemberIdentity Create([CanBeNull] MemberInfo property) + => property == null ? None : new MemberIdentity(property); + + public static MemberIdentity Create([CanBeNull] Navigation navigation) + => navigation?.GetIdentifyingMemberInfo() == null + ? Create(navigation?.Name) + : Create(navigation.GetIdentifyingMemberInfo()); + + public string Name + { + [DebuggerStepThrough] get => MemberInfo?.GetSimpleMemberName() ?? (string)_nameOrMember; + } + + public MemberInfo MemberInfo + { + [DebuggerStepThrough] get => _nameOrMember as MemberInfo; + } + + private string DebuggerDisplay() + => Name ?? "NONE"; + } +} diff --git a/src/EFCore/Metadata/PropertyParameterBinding.cs b/src/EFCore/Metadata/PropertyParameterBinding.cs index 3d62da40517..3d70dde51ad 100644 --- a/src/EFCore/Metadata/PropertyParameterBinding.cs +++ b/src/EFCore/Metadata/PropertyParameterBinding.cs @@ -3,7 +3,7 @@ using System.Linq.Expressions; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Metadata diff --git a/src/EFCore/Query/Pipeline/CollectionShaperExpression.cs b/src/EFCore/Query/CollectionShaperExpression.cs similarity index 81% rename from src/EFCore/Query/Pipeline/CollectionShaperExpression.cs rename to src/EFCore/Query/CollectionShaperExpression.cs index 2cbf752642b..8dc82978528 100644 --- a/src/EFCore/Query/Pipeline/CollectionShaperExpression.cs +++ b/src/EFCore/Query/CollectionShaperExpression.cs @@ -5,10 +5,8 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class CollectionShaperExpression : Expression, IPrintable { @@ -32,7 +30,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(projection, innerShaper); } - public CollectionShaperExpression Update(Expression projection, Expression innerShaper) + public virtual CollectionShaperExpression Update(Expression projection, Expression innerShaper) => projection != Projection || innerShaper != InnerShaper ? new CollectionShaperExpression(projection, innerShaper, Navigation, ElementType) : this; @@ -40,10 +38,10 @@ public CollectionShaperExpression Update(Expression projection, Expression inner public override ExpressionType NodeType => ExpressionType.Extension; public override Type Type => Navigation?.ClrType ?? typeof(List<>).MakeGenericType(ElementType); - public Expression Projection { get; } - public Expression InnerShaper { get; } - public INavigation Navigation { get; } - public Type ElementType { get; } + public virtual Expression Projection { get; } + public virtual Expression InnerShaper { get; } + public virtual INavigation Navigation { get; } + public virtual Type ElementType { get; } public virtual void Print(ExpressionPrinter expressionPrinter) { diff --git a/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs b/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs index 47b6ce810ac..820076dfa60 100644 --- a/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs +++ b/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs @@ -50,9 +50,14 @@ public sealed class CompiledQueryCacheKeyGeneratorDependencies /// 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. + /// /// - /// The model that queries will be written against. - /// The context that queries will be executed for. + [EntityFrameworkInternal] public CompiledQueryCacheKeyGeneratorDependencies([NotNull] IModel model, [NotNull] ICurrentDbContext currentContext) { Check.NotNull(model, nameof(model)); diff --git a/src/EFCore/Query/Internal/EntityMaterializerSource.cs b/src/EFCore/Query/EntityMaterializerSource.cs similarity index 72% rename from src/EFCore/Query/Internal/EntityMaterializerSource.cs rename to src/EFCore/Query/EntityMaterializerSource.cs index 8dfa685efb9..e4cc2f5f10b 100644 --- a/src/EFCore/Query/Internal/EntityMaterializerSource.cs +++ b/src/EFCore/Query/EntityMaterializerSource.cs @@ -9,6 +9,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; @@ -16,16 +17,10 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.EntityFrameworkCore.Query.Internal +namespace Microsoft.EntityFrameworkCore.Query { /// /// - /// 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. - /// - /// /// The service lifetime is . This means a single instance /// is used by many instances. The implementation must be thread-safe. /// This service cannot depend on services registered as . @@ -35,12 +30,10 @@ public class EntityMaterializerSource : IEntityMaterializerSource { private ConcurrentDictionary> _materializers; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// + public EntityMaterializerSource([NotNull] EntityMaterializerSourceDependencies dependencies) + { + } + public virtual Expression CreateReadValueExpression( Expression valueBufferExpression, Type type, @@ -52,12 +45,6 @@ public virtual Expression CreateReadValueExpression( Expression.Constant(index), Expression.Constant(property, typeof(IPropertyBase))); - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public static readonly MethodInfo TryReadValueMethod = typeof(EntityMaterializerSource).GetTypeInfo() .GetDeclaredMethod(nameof(TryReadValue)); @@ -67,12 +54,6 @@ private static TValue TryReadValue( in ValueBuffer valueBuffer, int index, IPropertyBase property) => (TValue)valueBuffer[index]; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual Expression CreateMaterializeExpression( IEntityType entityType, string entityInstanceName, @@ -175,12 +156,6 @@ private ConcurrentDictionary> ref _materializers, () => new ConcurrentDictionary>()); - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual Func GetMaterializer(IEntityType entityType) => Materializers.GetOrAdd( entityType, e => diff --git a/src/EFCore/Query/EntityMaterializerSourceDependencies.cs b/src/EFCore/Query/EntityMaterializerSourceDependencies.cs new file mode 100644 index 00000000000..243bedbe2f4 --- /dev/null +++ b/src/EFCore/Query/EntityMaterializerSourceDependencies.cs @@ -0,0 +1,57 @@ +// 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.Infrastructure; +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 a single instance + /// is used by many instances. The implementation must be thread-safe. + /// This service cannot depend on services registered as . + /// + /// + public sealed class EntityMaterializerSourceDependencies + { + /// + /// + /// 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 EntityMaterializerSourceDependencies() + { + } + } +} diff --git a/src/EFCore/Query/Pipeline/EntityShaperExpression.cs b/src/EFCore/Query/EntityShaperExpression.cs similarity index 69% rename from src/EFCore/Query/Pipeline/EntityShaperExpression.cs rename to src/EFCore/Query/EntityShaperExpression.cs index af159c93869..048bd47ec55 100644 --- a/src/EFCore/Query/Pipeline/EntityShaperExpression.cs +++ b/src/EFCore/Query/EntityShaperExpression.cs @@ -4,10 +4,8 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class EntityShaperExpression : Expression, IPrintable { @@ -15,12 +13,12 @@ public EntityShaperExpression(IEntityType entityType, Expression valueBufferExpr { EntityType = entityType; ValueBufferExpression = valueBufferExpression; - Nullable = nullable; + IsNullable = nullable; } - public IEntityType EntityType { get; } - public Expression ValueBufferExpression { get; } - public bool Nullable { get; } + public virtual IEntityType EntityType { get; } + public virtual Expression ValueBufferExpression { get; } + public virtual bool IsNullable { get; } protected override Expression VisitChildren(ExpressionVisitor visitor) { @@ -29,25 +27,25 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(valueBufferExpression); } - public EntityShaperExpression WithEntityType(IEntityType entityType) + public virtual EntityShaperExpression WithEntityType(IEntityType entityType) => entityType != EntityType - ? new EntityShaperExpression(entityType, ValueBufferExpression, Nullable) + ? new EntityShaperExpression(entityType, ValueBufferExpression, IsNullable) : this; - public EntityShaperExpression MarkAsNullable() - => !Nullable + public virtual EntityShaperExpression MarkAsNullable() + => !IsNullable ? new EntityShaperExpression(EntityType, ValueBufferExpression, true) : this; - public EntityShaperExpression Update(Expression valueBufferExpression) + public virtual EntityShaperExpression Update(Expression valueBufferExpression) => valueBufferExpression != ValueBufferExpression - ? new EntityShaperExpression(EntityType, valueBufferExpression, Nullable) + ? new EntityShaperExpression(EntityType, valueBufferExpression, IsNullable) : this; public override Type Type => EntityType.ClrType; public override ExpressionType NodeType => ExpressionType.Extension; - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.StringBuilder.AppendLine(nameof(EntityShaperExpression) + ": "); using (expressionPrinter.StringBuilder.Indent()) @@ -60,8 +58,8 @@ public void Print(ExpressionPrinter expressionPrinter) expressionPrinter.StringBuilder.AppendLine(); } - expressionPrinter.StringBuilder.Append(nameof(Nullable) + ": "); - expressionPrinter.StringBuilder.AppendLine(Nullable); + expressionPrinter.StringBuilder.Append(nameof(IsNullable) + ": "); + expressionPrinter.StringBuilder.AppendLine(IsNullable); } } } diff --git a/src/EFCore/Query/Internal/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs similarity index 65% rename from src/EFCore/Query/Internal/ExpressionPrinter.cs rename to src/EFCore/Query/ExpressionPrinter.cs index ac498f65a35..9bdf160da74 100644 --- a/src/EFCore/Query/Internal/ExpressionPrinter.cs +++ b/src/EFCore/Query/ExpressionPrinter.cs @@ -11,18 +11,9 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Internal +namespace Microsoft.EntityFrameworkCore.Query { - /// - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - /// public class ExpressionPrinter : ExpressionVisitor { private readonly IndentedStringBuilder _stringBuilder; @@ -51,12 +42,6 @@ public class ExpressionPrinter : ExpressionVisitor { ExpressionType.ExclusiveOr, " ^ " } }; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public ExpressionPrinter() { _stringBuilder = new IndentedStringBuilder(); @@ -64,44 +49,14 @@ public ExpressionPrinter() _namelessParameters = new List(); } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual IndentedStringBuilder StringBuilder => _stringBuilder; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual bool RemoveFormatting { get; set; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual int? CharacterLimit { get; set; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual bool PrintConnections { get; set; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual void VisitList( IReadOnlyList items, Action joinAction = null) @@ -134,12 +89,6 @@ private void AppendLine([NotNull] string message = "") _stringBuilder.AppendLine(message); } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual string Print( Expression expression, bool removeFormatting = false, @@ -169,23 +118,11 @@ public virtual string Print( return queryPlan; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual string GenerateBinaryOperator(ExpressionType expressionType) { return _binaryOperandMap[expressionType]; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public override Expression Visit(Expression expression) { if (expression == null) @@ -307,12 +244,6 @@ public override Expression Visit(Expression expression) return expression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitBinary(BinaryExpression binaryExpression) { Visit(binaryExpression.Left); @@ -342,12 +273,6 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) return binaryExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitBlock(BlockExpression blockExpression) { AppendLine(); @@ -400,12 +325,6 @@ protected override Expression VisitBlock(BlockExpression blockExpression) return blockExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { Visit(conditionalExpression.Test); @@ -421,12 +340,6 @@ protected override Expression VisitConditional(ConditionalExpression conditional return conditionalExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitConstant(ConstantExpression constantExpression) { if (PrintConnections) @@ -486,12 +399,6 @@ private void Print(object value) _stringBuilder.Append(stringValue); } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitGoto(GotoExpression gotoExpression) { AppendLine("return (" + gotoExpression.Target.Type.ShortDisplayName() + ")" + gotoExpression.Target + " {"); @@ -505,12 +412,6 @@ protected override Expression VisitGoto(GotoExpression gotoExpression) return gotoExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitLabel(LabelExpression labelExpression) { _stringBuilder.Append(labelExpression.Target.ToString()); @@ -518,12 +419,6 @@ protected override Expression VisitLabel(LabelExpression labelExpression) return labelExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitLambda(Expression lambdaExpression) { _stringBuilder.Append("("); @@ -558,12 +453,6 @@ protected override Expression VisitLambda(Expression lambdaExpression) return lambdaExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitMember(MemberExpression memberExpression) { if (memberExpression.Expression != null) @@ -590,12 +479,6 @@ protected override Expression VisitMember(MemberExpression memberExpression) return memberExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression) { _stringBuilder.Append("new " + memberInitExpression.Type.ShortDisplayName()); @@ -641,12 +524,6 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp "Add" }; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (!methodCallExpression.IsEFProperty()) @@ -727,12 +604,6 @@ var argumentNames return methodCallExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitNew(NewExpression newExpression) { _stringBuilder.Append("new "); @@ -784,12 +655,6 @@ protected override Expression VisitNew(NewExpression newExpression) return newExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) { var isComplex = newArrayExpression.Expressions.Count > 1; @@ -826,12 +691,6 @@ protected override Expression VisitNewArray(NewArrayExpression newArrayExpressio return newArrayExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitParameter(ParameterExpression parameterExpression) { if (_parametersInScope.ContainsKey(parameterExpression)) @@ -869,12 +728,6 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres return parameterExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitUnary(UnaryExpression unaryExpression) { // ReSharper disable once SwitchStatementMissingSomeCases @@ -925,12 +778,6 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) return unaryExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitDefault(DefaultExpression defaultExpression) { _stringBuilder.Append("default(" + defaultExpression.Type.ShortDisplayName() + ")"); @@ -938,12 +785,6 @@ protected override Expression VisitDefault(DefaultExpression defaultExpression) return defaultExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitTry(TryExpression tryExpression) { _stringBuilder.Append("try { "); @@ -958,12 +799,6 @@ protected override Expression VisitTry(TryExpression tryExpression) return tryExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitIndex(IndexExpression indexExpression) { Visit(indexExpression.Object); @@ -974,12 +809,6 @@ protected override Expression VisitIndex(IndexExpression indexExpression) return indexExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) { _stringBuilder.Append("("); @@ -989,12 +818,6 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp return typeBinaryExpression; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected override Expression VisitExtension(Expression extensionExpression) { if (extensionExpression is IPrintable printable) @@ -1024,12 +847,6 @@ private void VisitArguments(IList arguments, Action appendAc } } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// protected virtual string PostProcess([NotNull] string queryPlan) { var processedPlan = queryPlan diff --git a/src/EFCore/Query/Expressions/Internal/IPrintable.cs b/src/EFCore/Query/Expressions/Internal/IPrintable.cs deleted file mode 100644 index a6dca4362f0..00000000000 --- a/src/EFCore/Query/Expressions/Internal/IPrintable.cs +++ /dev/null @@ -1,25 +0,0 @@ -// 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.Query.Internal; - -namespace Microsoft.EntityFrameworkCore.Query.Expressions.Internal -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public interface IPrintable - { - /// - /// 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. - /// - void Print([NotNull] ExpressionPrinter expressionPrinter); - } -} diff --git a/src/EFCore/Query/Pipeline/GroupByShaperExpression.cs b/src/EFCore/Query/GroupByShaperExpression.cs similarity index 79% rename from src/EFCore/Query/Pipeline/GroupByShaperExpression.cs rename to src/EFCore/Query/GroupByShaperExpression.cs index 82a8111a4e1..7995d525411 100644 --- a/src/EFCore/Query/Pipeline/GroupByShaperExpression.cs +++ b/src/EFCore/Query/GroupByShaperExpression.cs @@ -4,10 +4,8 @@ using System; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class GroupByShaperExpression : Expression, IPrintable { @@ -17,13 +15,13 @@ public GroupByShaperExpression(Expression keySelector, Expression elementSelecto ElementSelector = elementSelector; } - public Expression KeySelector { get; } - public Expression ElementSelector { get; } + public virtual Expression KeySelector { get; } + public virtual Expression ElementSelector { get; } public override Type Type => typeof(IGrouping<,>).MakeGenericType(KeySelector.Type, ElementSelector.Type); public override ExpressionType NodeType => ExpressionType.Extension; - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.StringBuilder.AppendLine("GroupBy("); expressionPrinter.StringBuilder.Append("KeySelector: "); @@ -42,7 +40,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return Update(keySelector, elementSelector); } - public GroupByShaperExpression Update(Expression keySelector, Expression elementSelector) + public virtual GroupByShaperExpression Update(Expression keySelector, Expression elementSelector) => keySelector != KeySelector || elementSelector != ElementSelector ? new GroupByShaperExpression(keySelector, elementSelector) : this; diff --git a/src/EFCore/Query/IParameterValues.cs b/src/EFCore/Query/IParameterValues.cs new file mode 100644 index 00000000000..38d3d9360fe --- /dev/null +++ b/src/EFCore/Query/IParameterValues.cs @@ -0,0 +1,19 @@ +// 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.Collections.Generic; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public interface IParameterValues + { + IReadOnlyDictionary ParameterValues { get; } + + void Add([NotNull] string name, [CanBeNull] object value); + + object Remove([NotNull] string name); + + void Replace([NotNull] string name, [CanBeNull] object value); + } +} diff --git a/src/EFCore/Query/IPrintable.cs b/src/EFCore/Query/IPrintable.cs new file mode 100644 index 00000000000..87b0a9c7b96 --- /dev/null +++ b/src/EFCore/Query/IPrintable.cs @@ -0,0 +1,12 @@ +// 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; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public interface IPrintable + { + void Print([NotNull] ExpressionPrinter expressionPrinter); + } +} diff --git a/src/EFCore/Query/Pipeline/IQueryCompilationContextFactory.cs b/src/EFCore/Query/IQueryCompilationContextFactory.cs similarity index 84% rename from src/EFCore/Query/Pipeline/IQueryCompilationContextFactory.cs rename to src/EFCore/Query/IQueryCompilationContextFactory.cs index 2f3cbaf7c73..b4055e91e74 100644 --- a/src/EFCore/Query/Pipeline/IQueryCompilationContextFactory.cs +++ b/src/EFCore/Query/IQueryCompilationContextFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IQueryCompilationContextFactory { diff --git a/src/EFCore/Query/Pipeline/IQueryOptimizingExpressionVisitorFactory.cs b/src/EFCore/Query/IQueryOptimizerFactory.cs similarity index 84% rename from src/EFCore/Query/Pipeline/IQueryOptimizingExpressionVisitorFactory.cs rename to src/EFCore/Query/IQueryOptimizerFactory.cs index d1f52fceee0..4f316bfdd73 100644 --- a/src/EFCore/Query/Pipeline/IQueryOptimizingExpressionVisitorFactory.cs +++ b/src/EFCore/Query/IQueryOptimizerFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IQueryOptimizerFactory { diff --git a/src/EFCore/Query/Pipeline/IQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs similarity index 87% rename from src/EFCore/Query/Pipeline/IQueryableMethodTranslatingExpressionVisitorFactory.cs rename to src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs index a3190059ede..408008ab76b 100644 --- a/src/EFCore/Query/Pipeline/IQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IQueryableMethodTranslatingExpressionVisitorFactory { diff --git a/src/EFCore/Query/Pipeline/IShapedQueryExpressionVisitorFactory.cs b/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs similarity index 86% rename from src/EFCore/Query/Pipeline/IShapedQueryExpressionVisitorFactory.cs rename to src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs index bef38cb4200..7e90e8c0fd6 100644 --- a/src/EFCore/Query/Pipeline/IShapedQueryExpressionVisitorFactory.cs +++ b/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IShapedQueryCompilingExpressionVisitorFactory { diff --git a/src/EFCore/Query/Pipeline/IShapedQueryOptimizingExpressionVisitorsFactory.cs b/src/EFCore/Query/IShapedQueryOptimizerFactory.cs similarity index 85% rename from src/EFCore/Query/Pipeline/IShapedQueryOptimizingExpressionVisitorsFactory.cs rename to src/EFCore/Query/IShapedQueryOptimizerFactory.cs index 43ead0baa10..b64e718ebba 100644 --- a/src/EFCore/Query/Pipeline/IShapedQueryOptimizingExpressionVisitorsFactory.cs +++ b/src/EFCore/Query/IShapedQueryOptimizerFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public interface IShapedQueryOptimizerFactory { diff --git a/src/EFCore/Query/NavigationExpansion/IncludeExpression.cs b/src/EFCore/Query/IncludeExpression.cs similarity index 92% rename from src/EFCore/Query/NavigationExpansion/IncludeExpression.cs rename to src/EFCore/Query/IncludeExpression.cs index d3ec0555d8f..c3a00c28de0 100644 --- a/src/EFCore/Query/NavigationExpansion/IncludeExpression.cs +++ b/src/EFCore/Query/IncludeExpression.cs @@ -4,10 +4,8 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query { public class IncludeExpression : Expression, IPrintable { diff --git a/src/EFCore/Query/Pipeline/AllAnyToContainsRewritingExpressionVisitor.cs b/src/EFCore/Query/Internal/AllAnyToContainsRewritingExpressionVisitor.cs similarity index 97% rename from src/EFCore/Query/Pipeline/AllAnyToContainsRewritingExpressionVisitor.cs rename to src/EFCore/Query/Internal/AllAnyToContainsRewritingExpressionVisitor.cs index 4b831a34833..e6b13e8f5ae 100644 --- a/src/EFCore/Query/Pipeline/AllAnyToContainsRewritingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/AllAnyToContainsRewritingExpressionVisitor.cs @@ -3,9 +3,9 @@ using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class AllAnyToContainsRewritingExpressionVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/Internal/CompiledQueryBase.cs b/src/EFCore/Query/Internal/CompiledQueryBase.cs index 9bb34bda89d..c2e140532d0 100644 --- a/src/EFCore/Query/Internal/CompiledQueryBase.cs +++ b/src/EFCore/Query/Internal/CompiledQueryBase.cs @@ -67,7 +67,7 @@ protected virtual TResult ExecuteCore( for (var i = 0; i < parameters.Length; i++) { - queryContext.AddParameter( + queryContext.Add( CompiledQueryCache.CompiledQueryParameterPrefix + _queryExpression.Parameters[i + 1].Name, parameters[i]); } diff --git a/src/EFCore/Query/Pipeline/EntityEqualityRewritingExpressionVisitor.cs b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs similarity index 97% rename from src/EFCore/Query/Pipeline/EntityEqualityRewritingExpressionVisitor.cs rename to src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs index 4fbc6eec30c..1d7b6284eed 100644 --- a/src/EFCore/Query/Pipeline/EntityEqualityRewritingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs @@ -8,14 +8,13 @@ using System.Reflection; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { /// /// Rewrites comparisons of entities (as opposed to comparisons of their properties) into comparison of their keys. @@ -43,7 +42,7 @@ public EntityEqualityRewritingExpressionVisitor(QueryCompilationContext queryCom _logger = queryCompilationContext.Logger; } - public Expression Rewrite(Expression expression) => Unwrap(Visit(expression)); + public virtual Expression Rewrite(Expression expression) => Unwrap(Visit(expression)); protected override Expression VisitConstant(ConstantExpression constantExpression) => constantExpression.IsEntityQueryable() @@ -511,7 +510,7 @@ protected virtual Expression VisitJoinMethodCall(MethodCallExpression methodCall /// Replaces the lambda's single parameter with a type wrapper based on the given source, and then visits /// the lambda's body. /// - protected LambdaExpression RewriteAndVisitLambda(LambdaExpression lambda, EntityReferenceExpression source) + protected virtual LambdaExpression RewriteAndVisitLambda(LambdaExpression lambda, EntityReferenceExpression source) => Expression.Lambda( lambda.Type, Visit(ReplacingExpressionVisitor.Replace( @@ -525,17 +524,25 @@ protected LambdaExpression RewriteAndVisitLambda(LambdaExpression lambda, Entity /// Replaces the lambda's two parameters with type wrappers based on the given sources, and then visits /// the lambda's body. /// - protected LambdaExpression RewriteAndVisitLambda(LambdaExpression lambda, + protected virtual LambdaExpression RewriteAndVisitLambda(LambdaExpression lambda, EntityReferenceExpression source1, EntityReferenceExpression source2) - => Expression.Lambda( + { + Expression original1 = lambda.Parameters[0]; + Expression replacement1 = source1.Update(lambda.Parameters[0]); + Expression original2 = lambda.Parameters[1]; + Expression replacement2 = source2.Update(lambda.Parameters[1]); + return Expression.Lambda( lambda.Type, - Visit(ReplacingExpressionVisitor.Replace( - lambda.Parameters[0], source1.Update(lambda.Parameters[0]), - lambda.Parameters[1], source2.Update(lambda.Parameters[1]), - lambda.Body)), + Visit( + new ReplacingExpressionVisitor( + new Dictionary { + { original1, replacement1 }, + { original2, replacement2 } + }).Visit(lambda.Body)), lambda.TailCall, lambda.Parameters); + } /// /// Receives already-visited left and right operands of an equality expression and applies entity equality rewriting to them, @@ -697,7 +704,7 @@ protected virtual Expression VisitNullConditional(NullConditionalExpression expr /// doing so can result in application failures when updating to a new Entity Framework Core release. /// // TODO: DRY with NavigationExpansionHelpers - protected Expression CreateKeyAccessExpression( + protected virtual Expression CreateKeyAccessExpression( [NotNull] Expression target, [NotNull] IReadOnlyList properties) => properties.Count == 1 diff --git a/src/EFCore/Query/Pipeline/EnumerableToQueryableReMappingExpressionVisitor.cs b/src/EFCore/Query/Internal/EnumerableToQueryableReMappingExpressionVisitor.cs similarity index 99% rename from src/EFCore/Query/Pipeline/EnumerableToQueryableReMappingExpressionVisitor.cs rename to src/EFCore/Query/Internal/EnumerableToQueryableReMappingExpressionVisitor.cs index ab45300f56e..5ab4151a7a0 100644 --- a/src/EFCore/Query/Pipeline/EnumerableToQueryableReMappingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/EnumerableToQueryableReMappingExpressionVisitor.cs @@ -8,7 +8,7 @@ using System.Linq.Expressions; using System.Reflection; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class EnumerableToQueryableReMappingExpressionVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs b/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs index 6ea6b179887..fd3ec766bc0 100644 --- a/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs +++ b/src/EFCore/Query/Internal/ExpressionEqualityComparer.cs @@ -7,7 +7,6 @@ using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; // ReSharper disable SwitchStatementMissingSomeCases // ReSharper disable ForCanBeConvertedToForeach diff --git a/src/EFCore/Query/Pipeline/FunctionPreprocessingVisitor.cs b/src/EFCore/Query/Internal/FunctionPreprocessingVisitor.cs similarity index 98% rename from src/EFCore/Query/Pipeline/FunctionPreprocessingVisitor.cs rename to src/EFCore/Query/Internal/FunctionPreprocessingVisitor.cs index 466a35607ec..2330c770cd4 100644 --- a/src/EFCore/Query/Pipeline/FunctionPreprocessingVisitor.cs +++ b/src/EFCore/Query/Internal/FunctionPreprocessingVisitor.cs @@ -4,7 +4,7 @@ using System.Linq.Expressions; using System.Reflection; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class FunctionPreprocessingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/Pipeline/GroupJoinFlatteningExpressionVisitor.cs b/src/EFCore/Query/Internal/GroupJoinFlatteningExpressionVisitor.cs similarity index 99% rename from src/EFCore/Query/Pipeline/GroupJoinFlatteningExpressionVisitor.cs rename to src/EFCore/Query/Internal/GroupJoinFlatteningExpressionVisitor.cs index 3ce69608298..03cb7544bc3 100644 --- a/src/EFCore/Query/Pipeline/GroupJoinFlatteningExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/GroupJoinFlatteningExpressionVisitor.cs @@ -8,7 +8,7 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class GroupJoinFlatteningExpressionVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/Internal/IParameterValues.cs b/src/EFCore/Query/Internal/IParameterValues.cs deleted file mode 100644 index 6ddb9c999cf..00000000000 --- a/src/EFCore/Query/Internal/IParameterValues.cs +++ /dev/null @@ -1,49 +0,0 @@ -// 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.Collections.Generic; -using JetBrains.Annotations; - -namespace Microsoft.EntityFrameworkCore.Query.Internal -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public interface IParameterValues - { - /// - /// 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. - /// - IReadOnlyDictionary ParameterValues { get; } - - /// - /// 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. - /// - void AddParameter([NotNull] string name, [CanBeNull] object value); - - /// - /// 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. - /// - object RemoveParameter([NotNull] string name); - - /// - /// 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. - /// - void SetParameter([NotNull] string name, [CanBeNull] object value); - } -} diff --git a/src/EFCore/Query/Pipeline/NegationOptimizingVisitor.cs b/src/EFCore/Query/Internal/NegationOptimizingVisitor.cs similarity index 98% rename from src/EFCore/Query/Pipeline/NegationOptimizingVisitor.cs rename to src/EFCore/Query/Internal/NegationOptimizingVisitor.cs index 099658d90a3..b8f50c79b02 100644 --- a/src/EFCore/Query/Pipeline/NegationOptimizingVisitor.cs +++ b/src/EFCore/Query/Internal/NegationOptimizingVisitor.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq.Expressions; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class NegationOptimizingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/Pipeline/NullCheckRemovingExpressionVisitor.cs b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs similarity index 95% rename from src/EFCore/Query/Pipeline/NullCheckRemovingExpressionVisitor.cs rename to src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs index 6a98170ee9a..02b35326e4d 100644 --- a/src/EFCore/Query/Pipeline/NullCheckRemovingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs @@ -3,10 +3,8 @@ using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class NullCheckRemovingExpressionVisitor : ExpressionVisitor { @@ -15,10 +13,6 @@ private readonly NullSafeAccessVerifyingExpressionVisitor _nullSafeAccessVerifyi private readonly NullConditionalRemovingExpressionVisitor _nullConditionalRemovingExpressionVisitor = new NullConditionalRemovingExpressionVisitor(); - public NullCheckRemovingExpressionVisitor() - { - } - protected override Expression VisitConditional(ConditionalExpression conditionalExpression) { var test = Visit(conditionalExpression.Test); diff --git a/src/EFCore/Query/Expressions/Internal/NullSafeEqualExpression.cs b/src/EFCore/Query/Internal/NullSafeEqualExpression.cs similarity index 98% rename from src/EFCore/Query/Expressions/Internal/NullSafeEqualExpression.cs rename to src/EFCore/Query/Internal/NullSafeEqualExpression.cs index 70c79287d9c..e2f396220ae 100644 --- a/src/EFCore/Query/Expressions/Internal/NullSafeEqualExpression.cs +++ b/src/EFCore/Query/Internal/NullSafeEqualExpression.cs @@ -4,10 +4,9 @@ using System; using System.Linq.Expressions; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Query.Expressions.Internal +namespace Microsoft.EntityFrameworkCore.Query.Internal { /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Query/Pipeline/ParameterExtractingExpressionVisitor.cs b/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs similarity index 99% rename from src/EFCore/Query/Pipeline/ParameterExtractingExpressionVisitor.cs rename to src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs index 2acb85eb3c5..bff15c324b6 100644 --- a/src/EFCore/Query/Pipeline/ParameterExtractingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs @@ -9,10 +9,9 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -283,7 +282,7 @@ var compilerPrefixIndex + "_" + _parameterValues.ParameterValues.Count; - _parameterValues.AddParameter(parameterName, parameterValue); + _parameterValues.Add(parameterName, parameterValue); var parameter = Expression.Parameter(expression.Type, parameterName); diff --git a/src/EFCore/Query/Pipeline/QueryCompilationContextFactory.cs b/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs similarity index 95% rename from src/EFCore/Query/Pipeline/QueryCompilationContextFactory.cs rename to src/EFCore/Query/Internal/QueryCompilationContextFactory.cs index ac11fe7dcbc..517ffe6d4d9 100644 --- a/src/EFCore/Query/Pipeline/QueryCompilationContextFactory.cs +++ b/src/EFCore/Query/Internal/QueryCompilationContextFactory.cs @@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class QueryCompilationContextFactory : IQueryCompilationContextFactory { @@ -38,7 +38,7 @@ public QueryCompilationContextFactory( _logger = logger; } - public QueryCompilationContext Create(bool async) + public virtual QueryCompilationContext Create(bool async) => new QueryCompilationContext( _model, _queryOptimizerFactory, diff --git a/src/EFCore/Query/Internal/QueryCompiler.cs b/src/EFCore/Query/Internal/QueryCompiler.cs index 71402a6ad49..eb7540a3645 100644 --- a/src/EFCore/Query/Internal/QueryCompiler.cs +++ b/src/EFCore/Query/Internal/QueryCompiler.cs @@ -8,7 +8,6 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; diff --git a/src/EFCore/Query/Pipeline/QueryMetadataExtractingExpressionVisitor.cs b/src/EFCore/Query/Internal/QueryMetadataExtractingExpressionVisitor.cs similarity index 94% rename from src/EFCore/Query/Pipeline/QueryMetadataExtractingExpressionVisitor.cs rename to src/EFCore/Query/Internal/QueryMetadataExtractingExpressionVisitor.cs index 94833f8b633..f848954c937 100644 --- a/src/EFCore/Query/Pipeline/QueryMetadataExtractingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/QueryMetadataExtractingExpressionVisitor.cs @@ -3,7 +3,7 @@ using System.Linq.Expressions; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class QueryMetadataExtractingExpressionVisitor : ExpressionVisitor { @@ -26,7 +26,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp || genericMethodDefinition == EntityFrameworkQueryableExtensions.AsNoTrackingMethodInfo) { var innerQueryable = Visit(methodCallExpression.Arguments[0]); - _queryCompilationContext.TrackQueryResults + _queryCompilationContext.IsTracking = genericMethodDefinition == EntityFrameworkQueryableExtensions.AsTrackingMethodInfo; return innerQueryable; diff --git a/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitorFactory.cs b/src/EFCore/Query/Internal/QueryOptimizerFactory.cs similarity index 67% rename from src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitorFactory.cs rename to src/EFCore/Query/Internal/QueryOptimizerFactory.cs index d42aebaf1e9..1d789453aa8 100644 --- a/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitorFactory.cs +++ b/src/EFCore/Query/Internal/QueryOptimizerFactory.cs @@ -1,11 +1,11 @@ // 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. -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class QueryOptimizerFactory : IQueryOptimizerFactory { - public QueryOptimizer Create(QueryCompilationContext queryCompilationContext) + public virtual QueryOptimizer Create(QueryCompilationContext queryCompilationContext) => new QueryOptimizer(queryCompilationContext); } } diff --git a/src/EFCore/Query/Pipeline/ShapedQueryOptimizingExpressionVisitorsFactory.cs b/src/EFCore/Query/Internal/ShapedQueryOptimizerFactory.cs similarity index 88% rename from src/EFCore/Query/Pipeline/ShapedQueryOptimizingExpressionVisitorsFactory.cs rename to src/EFCore/Query/Internal/ShapedQueryOptimizerFactory.cs index 687404fb198..4617e9bd7a3 100644 --- a/src/EFCore/Query/Pipeline/ShapedQueryOptimizingExpressionVisitorsFactory.cs +++ b/src/EFCore/Query/Internal/ShapedQueryOptimizerFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query.Internal { public class ShapedQueryOptimizerFactory : IShapedQueryOptimizerFactory { diff --git a/src/EFCore/Query/NavigationExpansion/MaterializeCollectionNavigationExpression.cs b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs similarity index 88% rename from src/EFCore/Query/NavigationExpansion/MaterializeCollectionNavigationExpression.cs rename to src/EFCore/Query/MaterializeCollectionNavigationExpression.cs index b0b652980da..daa423d1ded 100644 --- a/src/EFCore/Query/NavigationExpansion/MaterializeCollectionNavigationExpression.cs +++ b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs @@ -4,10 +4,8 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query { public class MaterializeCollectionNavigationExpression : Expression, IPrintable { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/CollectionNavigationRewritingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/CollectionNavigationRewritingVisitor.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/CollectionNavigationRewritingVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/CollectionNavigationRewritingVisitor.cs index a11df117f9b..09ce2a6fb28 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/CollectionNavigationRewritingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/CollectionNavigationRewritingVisitor.cs @@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { /// /// Rewrites collection navigations into subqueries, e.g.: diff --git a/src/EFCore/Query/NavigationExpansion/CorrelationPredicateExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/CorrelationPredicateExpression.cs similarity index 95% rename from src/EFCore/Query/NavigationExpansion/CorrelationPredicateExpression.cs rename to src/EFCore/Query/NavigationExpansion/Internal/CorrelationPredicateExpression.cs index a6c4eb6d709..f93e9f205d7 100644 --- a/src/EFCore/Query/NavigationExpansion/CorrelationPredicateExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/CorrelationPredicateExpression.cs @@ -5,11 +5,9 @@ using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class CorrelationPredicateExpression : Expression, IPrintable { diff --git a/src/EFCore/Query/NavigationExpansion/CustomRootExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/CustomRootExpression.cs similarity index 94% rename from src/EFCore/Query/NavigationExpansion/CustomRootExpression.cs rename to src/EFCore/Query/NavigationExpansion/Internal/CustomRootExpression.cs index 9cd67525425..ab5bf2ecc31 100644 --- a/src/EFCore/Query/NavigationExpansion/CustomRootExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/CustomRootExpression.cs @@ -5,10 +5,8 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class CustomRootExpression : Expression, IPrintable { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/ExpressionReplacingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/ExpressionReplacingVisitor.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/ExpressionReplacingVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/ExpressionReplacingVisitor.cs index c12a3f6ef1e..01c0833c642 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/ExpressionReplacingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/ExpressionReplacingVisitor.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq.Expressions; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class ExpressionReplacingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/NavigationExpansion/IncludeHelpers.cs b/src/EFCore/Query/NavigationExpansion/Internal/IncludeHelpers.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/IncludeHelpers.cs rename to src/EFCore/Query/NavigationExpansion/Internal/IncludeHelpers.cs index 2f27e02d165..2429c7c9a39 100644 --- a/src/EFCore/Query/NavigationExpansion/IncludeHelpers.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/IncludeHelpers.cs @@ -5,7 +5,7 @@ using System.Linq; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public static class IncludeHelpers { diff --git a/src/EFCore/Query/NavigationExpansion/LinqMethodHelpers.cs b/src/EFCore/Query/NavigationExpansion/Internal/LinqMethodHelpers.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/LinqMethodHelpers.cs rename to src/EFCore/Query/NavigationExpansion/Internal/LinqMethodHelpers.cs index f9838320954..0f15cc47e77 100644 --- a/src/EFCore/Query/NavigationExpansion/LinqMethodHelpers.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/LinqMethodHelpers.cs @@ -6,7 +6,7 @@ using System.Linq.Expressions; using System.Reflection; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public static class LinqMethodHelpers { diff --git a/src/EFCore/Query/NavigationExpansion/NavigationBindingExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationBindingExpression.cs similarity index 95% rename from src/EFCore/Query/NavigationExpansion/NavigationBindingExpression.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationBindingExpression.cs index 8d5ef8f338a..c654878e37a 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationBindingExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationBindingExpression.cs @@ -6,10 +6,8 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationBindingExpression : Expression, IPrintable { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationComparisonOptimizingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationComparisonOptimizingVisitor.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/NavigationComparisonOptimizingVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationComparisonOptimizingVisitor.cs index c8c65d738e5..d420a0a71cb 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationComparisonOptimizingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationComparisonOptimizingVisitor.cs @@ -6,7 +6,7 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationComparisonOptimizingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpandingVisitor.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationExpandingVisitor.cs index 228520d3154..64956f56f59 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpandingVisitor.cs @@ -9,9 +9,8 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public partial class NavigationExpandingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpandingVisitor_MethodCall.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationExpandingVisitor_MethodCall.cs index 15ca7bb3889..b88f2491cc7 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpandingVisitor_MethodCall.cs @@ -7,13 +7,13 @@ using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public partial class NavigationExpandingVisitor { @@ -1378,11 +1378,14 @@ protected override Expression VisitConstant(ConstantExpression constantExpressio NavigationExpansionExpressionState outerState, NavigationExpansionExpressionState innerState) { + Expression original1 = resultSelector.Parameters[0]; + Expression original2 = resultSelector.Parameters[1]; var remappedResultSelectorBody = - ReplacingExpressionVisitor.Replace( - resultSelector.Parameters[0], outerState.PendingSelector.Body, - resultSelector.Parameters[1], innerState.PendingSelector.Body, - resultSelector.Body); + new ReplacingExpressionVisitor( + new Dictionary { + { original1, outerState.PendingSelector.Body }, + { original2, innerState.PendingSelector.Body } + }).Visit(resultSelector.Body); var outerBinder = new NavigationPropertyBindingVisitor( outerState.CurrentParameter, diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpression.cs similarity index 97% rename from src/EFCore/Query/NavigationExpansion/NavigationExpansionExpression.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpression.cs index 8bbdc47547a..4a77cd5cd00 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpression.cs @@ -7,10 +7,8 @@ using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationExpansionExpression : Expression, IPrintable { diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpressionState.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpressionState.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/NavigationExpansionExpressionState.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpressionState.cs index ff83239b93b..be38e431f3a 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpressionState.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionExpressionState.cs @@ -6,7 +6,7 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationExpansionExpressionState { diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionHelpers.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionHelpers.cs index cfce1a6b499..e5e3ee3c91e 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionHelpers.cs @@ -8,10 +8,9 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public static class NavigationExpansionHelpers { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionReducingVisitor.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionReducingVisitor.cs index 684c7f95a21..c8cb8877e91 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionReducingVisitor.cs @@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationExpansionReducingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionRootExpression.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionRootExpression.cs similarity index 95% rename from src/EFCore/Query/NavigationExpansion/NavigationExpansionRootExpression.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionRootExpression.cs index 22311512a96..383eae7ab84 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionRootExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationExpansionRootExpression.cs @@ -7,10 +7,8 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationExpansionRootExpression : Expression, IPrintable { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationPropertyBindingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationPropertyBindingVisitor.cs similarity index 98% rename from src/EFCore/Query/NavigationExpansion/Visitors/NavigationPropertyBindingVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationPropertyBindingVisitor.cs index 961c195ba9b..85a02223787 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationPropertyBindingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationPropertyBindingVisitor.cs @@ -4,10 +4,9 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationPropertyBindingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationPropertyUnbindingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationPropertyUnbindingVisitor.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/NavigationPropertyUnbindingVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationPropertyUnbindingVisitor.cs index 0c3f5e022d7..9dc1ae5080a 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationPropertyUnbindingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationPropertyUnbindingVisitor.cs @@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationPropertyUnbindingVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/NavigationExpansion/NavigationState.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationState.cs similarity index 98% rename from src/EFCore/Query/NavigationExpansion/NavigationState.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationState.cs index 5f0a5ab361a..c5bd9beea0f 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationState.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationState.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public enum NavigationState { diff --git a/src/EFCore/Query/NavigationExpansion/NavigationTreeNode.cs b/src/EFCore/Query/NavigationExpansion/Internal/NavigationTreeNode.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/NavigationTreeNode.cs rename to src/EFCore/Query/NavigationExpansion/Internal/NavigationTreeNode.cs index 583969ca31c..1bf2a5ab685 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationTreeNode.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/NavigationTreeNode.cs @@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class NavigationTreeNode { diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/PendingSelectorIncludeVisitor.cs b/src/EFCore/Query/NavigationExpansion/Internal/PendingSelectorIncludeVisitor.cs similarity index 99% rename from src/EFCore/Query/NavigationExpansion/Visitors/PendingSelectorIncludeVisitor.cs rename to src/EFCore/Query/NavigationExpansion/Internal/PendingSelectorIncludeVisitor.cs index 570cb65a0a6..fe9750ab920 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/PendingSelectorIncludeVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/PendingSelectorIncludeVisitor.cs @@ -4,11 +4,11 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class PendingSelectorIncludeVisitor : ExpressionVisitor { diff --git a/src/EFCore/Query/NavigationExpansion/SourceMapping.cs b/src/EFCore/Query/NavigationExpansion/Internal/SourceMapping.cs similarity index 97% rename from src/EFCore/Query/NavigationExpansion/SourceMapping.cs rename to src/EFCore/Query/NavigationExpansion/Internal/SourceMapping.cs index bad61c9187f..e60a5cc783e 100644 --- a/src/EFCore/Query/NavigationExpansion/SourceMapping.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/SourceMapping.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Metadata; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public class SourceMapping { diff --git a/src/EFCore/Query/NavigationExpansion/TransparentIdentifier.cs b/src/EFCore/Query/NavigationExpansion/Internal/TransparentIdentifier.cs similarity index 98% rename from src/EFCore/Query/NavigationExpansion/TransparentIdentifier.cs rename to src/EFCore/Query/NavigationExpansion/Internal/TransparentIdentifier.cs index fc2044f36c0..d77b823f456 100644 --- a/src/EFCore/Query/NavigationExpansion/TransparentIdentifier.cs +++ b/src/EFCore/Query/NavigationExpansion/Internal/TransparentIdentifier.cs @@ -3,7 +3,7 @@ using JetBrains.Annotations; -namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal { public readonly struct TransparentIdentifier { diff --git a/src/EFCore/Query/Expressions/Internal/NullConditionalExpression.cs b/src/EFCore/Query/NullConditionalExpression.cs similarity index 92% rename from src/EFCore/Query/Expressions/Internal/NullConditionalExpression.cs rename to src/EFCore/Query/NullConditionalExpression.cs index b91f4960551..0e2317a1f68 100644 --- a/src/EFCore/Query/Expressions/Internal/NullConditionalExpression.cs +++ b/src/EFCore/Query/NullConditionalExpression.cs @@ -5,12 +5,11 @@ using System.Collections.Generic; using System.Linq.Expressions; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Utilities; -namespace Microsoft.EntityFrameworkCore.Query.Expressions.Internal +namespace Microsoft.EntityFrameworkCore.Query { /// /// Expression representing null-conditional access. @@ -118,12 +117,6 @@ public virtual Expression Update(Expression newCaller, Expression newAccessOpera ? new NullConditionalExpression(newCaller, newAccessOperation) : this; - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public virtual void Print(ExpressionPrinter expressionPrinter) { if (AccessOperation is MemberExpression memberExpression) diff --git a/src/EFCore/Query/Pipeline/ProjectionBindingExpression.cs b/src/EFCore/Query/ProjectionBindingExpression.cs similarity index 87% rename from src/EFCore/Query/Pipeline/ProjectionBindingExpression.cs rename to src/EFCore/Query/ProjectionBindingExpression.cs index 26ce322e1fb..00bbe1923ec 100644 --- a/src/EFCore/Query/Pipeline/ProjectionBindingExpression.cs +++ b/src/EFCore/Query/ProjectionBindingExpression.cs @@ -5,11 +5,9 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class ProjectionBindingExpression : Expression, IPrintable { @@ -34,16 +32,16 @@ public ProjectionBindingExpression(Expression queryExpression, IDictionary IndexMap { get; } + public virtual Expression QueryExpression { get; } + public virtual ProjectionMember ProjectionMember { get; } + public virtual int? Index { get; } + public virtual IDictionary IndexMap { get; } public override Type Type { get; } public override ExpressionType NodeType => ExpressionType.Extension; protected override Expression VisitChildren(ExpressionVisitor visitor) => this; - public void Print(ExpressionPrinter expressionPrinter) + public virtual void Print(ExpressionPrinter expressionPrinter) { expressionPrinter.StringBuilder.Append(nameof(ProjectionBindingExpression) + ": "); if (ProjectionMember != null) diff --git a/src/EFCore/Query/Pipeline/ProjectionMember.cs b/src/EFCore/Query/ProjectionMember.cs similarity index 89% rename from src/EFCore/Query/Pipeline/ProjectionMember.cs rename to src/EFCore/Query/ProjectionMember.cs index eaa421253b3..142e48fd49c 100644 --- a/src/EFCore/Query/Pipeline/ProjectionMember.cs +++ b/src/EFCore/Query/ProjectionMember.cs @@ -2,12 +2,12 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Linq; using System.Collections.Generic; -using System.Reflection; using System.Diagnostics; +using System.Linq; +using System.Reflection; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { [DebuggerDisplay("{ToString(), nq}")] public class ProjectionMember @@ -24,7 +24,7 @@ private ProjectionMember(IList memberChain) _memberChain = memberChain; } - public ProjectionMember AddMember(MemberInfo member) + public virtual ProjectionMember Append(MemberInfo member) { var existingChain = _memberChain.ToList(); existingChain.Add(member); @@ -32,7 +32,7 @@ public ProjectionMember AddMember(MemberInfo member) return new ProjectionMember(existingChain); } - public ProjectionMember ShiftMember(MemberInfo member) + public virtual ProjectionMember Prepend(MemberInfo member) { var existingChain = _memberChain.ToList(); existingChain.Insert(0, member); @@ -40,7 +40,7 @@ public ProjectionMember ShiftMember(MemberInfo member) return new ProjectionMember(existingChain); } - public MemberInfo LastMember => _memberChain.LastOrDefault(); + public virtual MemberInfo Last => _memberChain.LastOrDefault(); public override int GetHashCode() { diff --git a/src/EFCore/Query/Pipeline/QueryCompilationContext.cs b/src/EFCore/Query/QueryCompilationContext.cs similarity index 89% rename from src/EFCore/Query/Pipeline/QueryCompilationContext.cs rename to src/EFCore/Query/QueryCompilationContext.cs index 4bec2083e6a..0de543bdaa2 100644 --- a/src/EFCore/Query/Pipeline/QueryCompilationContext.cs +++ b/src/EFCore/Query/QueryCompilationContext.cs @@ -9,9 +9,8 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class QueryCompilationContext { @@ -40,8 +39,8 @@ public QueryCompilationContext( IDiagnosticsLogger logger, bool async) { - Async = async; - TrackQueryResults = currentContext.Context.ChangeTracker.QueryTrackingBehavior == QueryTrackingBehavior.TrackAll; + IsAsync = async; + IsTracking = currentContext.Context.ChangeTracker.QueryTrackingBehavior == QueryTrackingBehavior.TrackAll; Model = model; ContextOptions = contextOptions; ContextType = currentContext.Context.GetType(); @@ -53,11 +52,11 @@ public QueryCompilationContext( _shapedQueryCompilingExpressionVisitorFactory = shapedQueryCompilingExpressionVisitorFactory; } - public bool Async { get; } - public IModel Model { get; } - public IDbContextOptions ContextOptions { get; } - public bool TrackQueryResults { get; internal set; } - public ISet Tags { get; } = new HashSet(); + public virtual bool IsAsync { get; } + public virtual IModel Model { get; } + public virtual IDbContextOptions ContextOptions { get; } + public virtual bool IsTracking { get; internal set; } + public virtual ISet Tags { get; } = new HashSet(); public virtual IDiagnosticsLogger Logger { get; } public virtual Type ContextType { get; } @@ -100,7 +99,7 @@ public virtual Func CreateQueryExecutor(Expressi /// A lambda must be provided, which will extract the parameter's value from the QueryContext every time /// the query is executed. /// - public void RegisterRuntimeParameter(string name, LambdaExpression valueExtractor) + public virtual void RegisterRuntimeParameter(string name, LambdaExpression valueExtractor) { if (valueExtractor.Parameters.Count != 1 || valueExtractor.Parameters[0] != QueryContextParameter @@ -133,6 +132,6 @@ private Expression InsertRuntimeParameters(Expression query) private static readonly MethodInfo _queryContextAddParameterMethodInfo = typeof(QueryContext) .GetTypeInfo() - .GetDeclaredMethod(nameof(QueryContext.AddParameter)); + .GetDeclaredMethod(nameof(QueryContext.Add)); } } diff --git a/src/EFCore/Query/QueryContext.cs b/src/EFCore/Query/QueryContext.cs index 8adb1c0d18f..d2c06d2819f 100644 --- a/src/EFCore/Query/QueryContext.cs +++ b/src/EFCore/Query/QueryContext.cs @@ -9,7 +9,6 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -114,7 +113,7 @@ public virtual IReadOnlyDictionary ParameterValues /// /// The name. /// The value. - public virtual void AddParameter(string name, object value) + public virtual void Add(string name, object value) { Check.NotEmpty(name, nameof(name)); @@ -126,7 +125,7 @@ public virtual void AddParameter(string name, object value) /// /// The name. /// The value. - public virtual void SetParameter(string name, object value) + public virtual void Replace(string name, object value) { Check.NotEmpty(name, nameof(name)); @@ -140,7 +139,7 @@ public virtual void SetParameter(string name, object value) /// /// The parameter value. /// - public virtual object RemoveParameter(string name) + public virtual object Remove(string name) { Check.NotEmpty(name, nameof(name)); diff --git a/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitor.cs b/src/EFCore/Query/QueryOptimizer.cs similarity index 90% rename from src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitor.cs rename to src/EFCore/Query/QueryOptimizer.cs index e3e24ca12c1..1138dca54c4 100644 --- a/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitor.cs +++ b/src/EFCore/Query/QueryOptimizer.cs @@ -4,9 +4,10 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors; +using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class QueryOptimizer { @@ -17,7 +18,7 @@ public QueryOptimizer(QueryCompilationContext queryCompilationContext) _queryCompilationContext = queryCompilationContext; } - public Expression Visit(Expression query) + public virtual Expression Visit(Expression query) { query = new QueryMetadataExtractingExpressionVisitor(_queryCompilationContext).Visit(query); query = new AllAnyToContainsRewritingExpressionVisitor().Visit(query); diff --git a/src/EFCore/Query/Pipeline/QueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs similarity index 65% rename from src/EFCore/Query/Pipeline/QueryableMethodTranslatingExpressionVisitor.cs rename to src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs index aba314fd8db..e8237a6ef8a 100644 --- a/src/EFCore/Query/Pipeline/QueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs @@ -2,14 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Visitors; +using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public abstract class QueryableMethodTranslatingExpressionVisitor : ExpressionVisitor { @@ -41,59 +41,59 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp break; case nameof(Queryable.All): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateAll( shapedQueryExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); case nameof(Queryable.Any): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateAny( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null); + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null); case nameof(Queryable.AsQueryable): return source; case nameof(Queryable.Average): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateAverage( - shapedQueryExpression, - methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, - methodCallExpression.Type); + shapedQueryExpression, + methodCallExpression.Arguments.Count == 2 + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, + methodCallExpression.Type); case nameof(Queryable.Cast): return TranslateCast(shapedQueryExpression, methodCallExpression.Method.GetGenericArguments()[0]); case nameof(Queryable.Concat): + { + var source2 = Visit(methodCallExpression.Arguments[1]); + if (source2 is ShapedQueryExpression innerShapedQueryExpression) { - var source2 = Visit(methodCallExpression.Arguments[1]); - if (source2 is ShapedQueryExpression innerShapedQueryExpression) - { - return TranslateConcat( - shapedQueryExpression, - innerShapedQueryExpression); - } + return TranslateConcat( + shapedQueryExpression, + innerShapedQueryExpression); } + } break; case nameof(Queryable.Contains) when argumentCount == 2: - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateContains(shapedQueryExpression, methodCallExpression.Arguments[1]); case nameof(Queryable.Count): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateCount( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null); + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null); case nameof(Queryable.DefaultIfEmpty): return TranslateDefaultIfEmpty( @@ -103,223 +103,223 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp : null); case nameof(Queryable.Distinct) - when argumentCount == 1: + when argumentCount == 1: return TranslateDistinct(shapedQueryExpression); case nameof(Queryable.ElementAt): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateElementAtOrDefault(shapedQueryExpression, methodCallExpression.Arguments[1], false); case nameof(Queryable.ElementAtOrDefault): - shapedQueryExpression.ResultType = ResultType.SingleWithDefault; + shapedQueryExpression.ResultCardinality = ResultCardinality.SingleOrDefault; return TranslateElementAtOrDefault(shapedQueryExpression, methodCallExpression.Arguments[1], true); case nameof(Queryable.Except) - when argumentCount == 2: + when argumentCount == 2: + { + var source2 = Visit(methodCallExpression.Arguments[1]); + if (source2 is ShapedQueryExpression innerShapedQueryExpression) { - var source2 = Visit(methodCallExpression.Arguments[1]); - if (source2 is ShapedQueryExpression innerShapedQueryExpression) - { - return TranslateExcept( - shapedQueryExpression, - innerShapedQueryExpression); - } + return TranslateExcept( + shapedQueryExpression, + innerShapedQueryExpression); } + } break; case nameof(Queryable.First): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateFirstOrDefault( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, methodCallExpression.Type, false); case nameof(Queryable.FirstOrDefault): - shapedQueryExpression.ResultType = ResultType.SingleWithDefault; + shapedQueryExpression.ResultCardinality = ResultCardinality.SingleOrDefault; return TranslateFirstOrDefault( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, methodCallExpression.Type, true); case nameof(Queryable.GroupBy): + { + var keySelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); + if (methodCallExpression.Arguments[argumentCount - 1] is ConstantExpression) + { + // This means last argument is EqualityComparer on key + // which is not supported + break; + } + + switch (argumentCount) { - var keySelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - if (methodCallExpression.Arguments[argumentCount - 1] is ConstantExpression) - { - // This means last argument is EqualityComparer on key - // which is not supported - break; - } - - switch (argumentCount) - { - case 2: + case 2: + return TranslateGroupBy( + shapedQueryExpression, + keySelector, + null, + null); + + case 3: + var lambda = methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(); + if (lambda.Parameters.Count == 1) + { return TranslateGroupBy( shapedQueryExpression, keySelector, - null, + lambda, null); - - case 3: - var lambda = methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(); - if (lambda.Parameters.Count == 1) - { - return TranslateGroupBy( - shapedQueryExpression, - keySelector, - lambda, - null); - } - else - { - return TranslateGroupBy( - shapedQueryExpression, - keySelector, - null, - lambda); - } - - case 4: + } + else + { return TranslateGroupBy( shapedQueryExpression, keySelector, - methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[3].UnwrapLambdaFromQuote()); - } + null, + lambda); + } + + case 4: + return TranslateGroupBy( + shapedQueryExpression, + keySelector, + methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[3].UnwrapLambdaFromQuote()); } + } break; case nameof(Queryable.GroupJoin) - when argumentCount == 5: + when argumentCount == 5: + { + var innerSource = Visit(methodCallExpression.Arguments[1]); + if (innerSource is ShapedQueryExpression innerShapedQueryExpression) { - var innerSource = Visit(methodCallExpression.Arguments[1]); - if (innerSource is ShapedQueryExpression innerShapedQueryExpression) - { - return TranslateGroupJoin( - shapedQueryExpression, - innerShapedQueryExpression, - methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); - } + return TranslateGroupJoin( + shapedQueryExpression, + innerShapedQueryExpression, + methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); } + } break; case nameof(Queryable.Intersect) - when argumentCount == 2: + when argumentCount == 2: + { + var source2 = Visit(methodCallExpression.Arguments[1]); + if (source2 is ShapedQueryExpression innerShapedQueryExpression) { - var source2 = Visit(methodCallExpression.Arguments[1]); - if (source2 is ShapedQueryExpression innerShapedQueryExpression) - { - return TranslateIntersect( - shapedQueryExpression, - innerShapedQueryExpression); - } + return TranslateIntersect( + shapedQueryExpression, + innerShapedQueryExpression); } + } break; case nameof(Queryable.Join) - when argumentCount == 5: + when argumentCount == 5: + { + var innerSource = Visit(methodCallExpression.Arguments[1]); + if (innerSource is ShapedQueryExpression innerShapedQueryExpression) { - var innerSource = Visit(methodCallExpression.Arguments[1]); - if (innerSource is ShapedQueryExpression innerShapedQueryExpression) - { - return TranslateJoin( - shapedQueryExpression, - innerShapedQueryExpression, - methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); - } + return TranslateJoin( + shapedQueryExpression, + innerShapedQueryExpression, + methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); } + } break; case nameof(QueryableExtensions.LeftJoin) - when argumentCount == 5: + when argumentCount == 5: + { + var innerSource = Visit(methodCallExpression.Arguments[1]); + if (innerSource is ShapedQueryExpression innerShapedQueryExpression) { - var innerSource = Visit(methodCallExpression.Arguments[1]); - if (innerSource is ShapedQueryExpression innerShapedQueryExpression) - { - return TranslateLeftJoin( - shapedQueryExpression, - innerShapedQueryExpression, - methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); - } + return TranslateLeftJoin( + shapedQueryExpression, + innerShapedQueryExpression, + methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); } + } break; case nameof(Queryable.Last): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateLastOrDefault( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, methodCallExpression.Type, false); case nameof(Queryable.LastOrDefault): - shapedQueryExpression.ResultType = ResultType.SingleWithDefault; + shapedQueryExpression.ResultCardinality = ResultCardinality.SingleOrDefault; return TranslateLastOrDefault( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, methodCallExpression.Type, true); case nameof(Queryable.LongCount): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateLongCount( - shapedQueryExpression, - methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null); + shapedQueryExpression, + methodCallExpression.Arguments.Count == 2 + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null); case nameof(Queryable.Max): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateMax( - shapedQueryExpression, - methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, - methodCallExpression.Type); + shapedQueryExpression, + methodCallExpression.Arguments.Count == 2 + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, + methodCallExpression.Type); case nameof(Queryable.Min): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateMin( - shapedQueryExpression, - methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, - methodCallExpression.Type); + shapedQueryExpression, + methodCallExpression.Arguments.Count == 2 + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, + methodCallExpression.Type); case nameof(Queryable.OfType): return TranslateOfType(shapedQueryExpression, methodCallExpression.Method.GetGenericArguments()[0]); case nameof(Queryable.OrderBy) - when argumentCount == 2: + when argumentCount == 2: return TranslateOrderBy( shapedQueryExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(), true); case nameof(Queryable.OrderByDescending) - when argumentCount == 2: + when argumentCount == 2: return TranslateOrderBy( shapedQueryExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(), @@ -348,22 +348,22 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp break; case nameof(Queryable.Single): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateSingleOrDefault( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, methodCallExpression.Type, false); case nameof(Queryable.SingleOrDefault): - shapedQueryExpression.ResultType = ResultType.SingleWithDefault; + shapedQueryExpression.ResultCardinality = ResultCardinality.SingleOrDefault; return TranslateSingleOrDefault( shapedQueryExpression, methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, methodCallExpression.Type, true); @@ -376,13 +376,13 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); case nameof(Queryable.Sum): - shapedQueryExpression.ResultType = ResultType.Single; + shapedQueryExpression.ResultCardinality = ResultCardinality.Single; return TranslateSum( - shapedQueryExpression, - methodCallExpression.Arguments.Count == 2 - ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() - : null, - methodCallExpression.Type); + shapedQueryExpression, + methodCallExpression.Arguments.Count == 2 + ? methodCallExpression.Arguments[1].UnwrapLambdaFromQuote() + : null, + methodCallExpression.Type); case nameof(Queryable.Take): return TranslateTake(shapedQueryExpression, methodCallExpression.Arguments[1]); @@ -393,30 +393,30 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); case nameof(Queryable.ThenBy) - when argumentCount == 2: + when argumentCount == 2: return TranslateThenBy( shapedQueryExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(), true); case nameof(Queryable.ThenByDescending) - when argumentCount == 2: + when argumentCount == 2: return TranslateThenBy( shapedQueryExpression, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(), false); case nameof(Queryable.Union) - when argumentCount == 2: + when argumentCount == 2: + { + var source2 = Visit(methodCallExpression.Arguments[1]); + if (source2 is ShapedQueryExpression innerShapedQueryExpression) { - var source2 = Visit(methodCallExpression.Arguments[1]); - if (source2 is ShapedQueryExpression innerShapedQueryExpression) - { - return TranslateUnion( - shapedQueryExpression, - innerShapedQueryExpression); - } + return TranslateUnion( + shapedQueryExpression, + innerShapedQueryExpression); } + } break; @@ -444,11 +444,6 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp : throw new NotImplementedException("Unhandled method: " + methodCallExpression.Method.Name); } - protected Type CreateTransparentIdentifierType(Type outerType, Type innerType) - { - return typeof(TransparentIdentifier<,>).MakeGenericType(outerType, innerType); - } - private class EntityShaperNullableMarkingExpressionVisitor : ExpressionVisitor { protected override Expression VisitExtension(Expression extensionExpression) @@ -462,7 +457,7 @@ protected override Expression VisitExtension(Expression extensionExpression) } } - protected ShapedQueryExpression TranslateResultSelectorForJoin( + protected virtual ShapedQueryExpression TranslateResultSelectorForJoin( ShapedQueryExpression outer, LambdaExpression resultSelector, Expression innerShaper, @@ -482,17 +477,22 @@ protected ShapedQueryExpression TranslateResultSelectorForJoin( var transparentIdentifierParameter = Expression.Parameter(transparentIdentifierType); + Expression original1 = resultSelector.Parameters[0]; + Expression replacement1 = AccessOuterTransparentField(transparentIdentifierType, transparentIdentifierParameter); + Expression original2 = resultSelector.Parameters[1]; + Expression replacement2 = AccessInnerTransparentField(transparentIdentifierType, transparentIdentifierParameter); var newResultSelector = Expression.Lambda( - ReplacingExpressionVisitor.Replace( - resultSelector.Parameters[0], AccessOuterTransparentField(transparentIdentifierType, transparentIdentifierParameter), - resultSelector.Parameters[1], AccessInnerTransparentField(transparentIdentifierType, transparentIdentifierParameter), - resultSelector.Body), + new ReplacingExpressionVisitor( + new Dictionary { + { original1, replacement1 }, + { original2, replacement2 } + }).Visit(resultSelector.Body), transparentIdentifierParameter); return TranslateSelect(outer, newResultSelector); } - protected ShapedQueryExpression TranslateResultSelectorForGroupJoin( + protected virtual ShapedQueryExpression TranslateResultSelectorForGroupJoin( #pragma warning disable IDE0060 // Remove unused parameter ShapedQueryExpression outer, Expression innerShaper, @@ -539,7 +539,7 @@ protected override Expression VisitExtension(Expression node) { return new ProjectionBindingExpression( _queryExpression, - projectionBindingExpression.ProjectionMember.ShiftMember(_memberShift), + projectionBindingExpression.ProjectionMember.Prepend(_memberShift), projectionBindingExpression.Type); } @@ -604,22 +604,4 @@ private static Expression AccessInnerTransparentField( protected abstract ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate); public abstract ShapedQueryExpression TranslateSubquery(Expression expression); } - - public readonly struct TransparentIdentifier - { - [UsedImplicitly] -#pragma warning disable IDE0051 // Remove unused private members - private TransparentIdentifier(TOuter outer, TInner inner) -#pragma warning restore IDE0051 // Remove unused private members - { - Outer = outer; - Inner = inner; - } - - [UsedImplicitly] - public readonly TOuter Outer; - - [UsedImplicitly] - public readonly TInner Inner; - } } diff --git a/src/EFCore/Query/Pipeline/ReplacingExpressionVisitor.cs b/src/EFCore/Query/ReplacingExpressionVisitor.cs similarity index 87% rename from src/EFCore/Query/Pipeline/ReplacingExpressionVisitor.cs rename to src/EFCore/Query/ReplacingExpressionVisitor.cs index 784d2a200e9..e01de68b2ba 100644 --- a/src/EFCore/Query/Pipeline/ReplacingExpressionVisitor.cs +++ b/src/EFCore/Query/ReplacingExpressionVisitor.cs @@ -4,9 +4,10 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class ReplacingExpressionVisitor : ExpressionVisitor { @@ -18,16 +19,6 @@ public static Expression Replace(Expression original, Expression replacement, Ex new Dictionary { { original, replacement } }).Visit(tree); } - public static Expression Replace( - Expression original1, Expression replacement1, Expression original2, Expression replacement2, Expression tree) - { - return new ReplacingExpressionVisitor( - new Dictionary { - { original1, replacement1 }, - { original2, replacement2 } - }).Visit(tree); - } - public ReplacingExpressionVisitor(IDictionary replacements) { _replacements = replacements; diff --git a/src/EFCore/Query/ResultCardinality.cs b/src/EFCore/Query/ResultCardinality.cs new file mode 100644 index 00000000000..48e5178c11a --- /dev/null +++ b/src/EFCore/Query/ResultCardinality.cs @@ -0,0 +1,13 @@ +// 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. +namespace Microsoft.EntityFrameworkCore.Query +{ + public enum ResultCardinality + { +#pragma warning disable SA1602 // Enumeration items should be documented + Enumerable, + Single, + SingleOrDefault +#pragma warning restore SA1602 // Enumeration items should be documented + } +} diff --git a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs similarity index 95% rename from src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs rename to src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs index 3cf14d86afe..86fb5f879f3 100644 --- a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs +++ b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs @@ -15,7 +15,7 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public abstract class ShapedQueryCompilingExpressionVisitor : ExpressionVisitor { @@ -39,11 +39,11 @@ protected ShapedQueryCompilingExpressionVisitor( IEntityMaterializerSource entityMaterializerSource) { _entityMaterializerSource = entityMaterializerSource; - TrackQueryResults = queryCompilationContext.TrackQueryResults; + IsTracking = queryCompilationContext.IsTracking; _entityMaterializerInjectingExpressionVisitor = - new EntityMaterializerInjectingExpressionVisitor(entityMaterializerSource, TrackQueryResults); - Async = queryCompilationContext.Async; - if (Async) + new EntityMaterializerInjectingExpressionVisitor(entityMaterializerSource, IsTracking); + IsAsync = queryCompilationContext.IsAsync; + if (IsAsync) { _cancellationTokenParameter = Expression.MakeMemberAccess( QueryCompilationContext.QueryContextParameter, @@ -52,22 +52,22 @@ protected ShapedQueryCompilingExpressionVisitor( } - protected bool TrackQueryResults { get; } + protected virtual bool IsTracking { get; } - protected bool Async { get; } + protected virtual bool IsAsync { get; } protected override Expression VisitExtension(Expression extensionExpression) { if (extensionExpression is ShapedQueryExpression shapedQueryExpression) { var serverEnumerable = VisitShapedQueryExpression(shapedQueryExpression); - switch (shapedQueryExpression.ResultType) + switch (shapedQueryExpression.ResultCardinality) { - case ResultType.Enumerable: + case ResultCardinality.Enumerable: return serverEnumerable; - case ResultType.Single: - return Async + case ResultCardinality.Single: + return IsAsync ? Expression.Call( _singleAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.TryGetSequenceType()), serverEnumerable, @@ -76,8 +76,8 @@ protected override Expression VisitExtension(Expression extensionExpression) _singleMethodInfo.MakeGenericMethod(serverEnumerable.Type.TryGetSequenceType()), serverEnumerable); - case ResultType.SingleWithDefault: - return Async + case ResultCardinality.SingleOrDefault: + return IsAsync ? Expression.Call( _singleOrDefaultAsyncMethodInfo.MakeGenericMethod(serverEnumerable.Type.TryGetSequenceType()), serverEnumerable, @@ -146,13 +146,6 @@ private static async Task SingleOrDefaultAsync( protected abstract Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression); - protected virtual Expression CreateReadValueExpression( - Expression valueBufferExpression, - Type type, - int index, - IPropertyBase property) - => _entityMaterializerSource.CreateReadValueExpression(valueBufferExpression, type, index, property); - protected virtual Expression InjectEntityMaterializers(Expression expression) => _entityMaterializerInjectingExpressionVisitor.Inject(expression); @@ -261,7 +254,7 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres typeof(object), p.GetIndex(), p))), - Expression.Constant(!entityShaperExpression.Nullable), + Expression.Constant(!entityShaperExpression.IsNullable), hasNullKeyVariable))); expressions.Add(Expression.IfThen( diff --git a/src/EFCore/Query/Pipeline/ShapedQueryExpression.cs b/src/EFCore/Query/ShapedQueryExpression.cs similarity index 75% rename from src/EFCore/Query/Pipeline/ShapedQueryExpression.cs rename to src/EFCore/Query/ShapedQueryExpression.cs index 9f57626fb21..c4fdb4abf6f 100644 --- a/src/EFCore/Query/Pipeline/ShapedQueryExpression.cs +++ b/src/EFCore/Query/ShapedQueryExpression.cs @@ -4,10 +4,8 @@ using System; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class ShapedQueryExpression : Expression, IPrintable { @@ -17,9 +15,9 @@ public ShapedQueryExpression(Expression queryExpression, Expression shaperExpres ShaperExpression = shaperExpression; } - public Expression QueryExpression { get; set; } - public ResultType ResultType { get; set; } - public Expression ShaperExpression { get; set; } + public virtual Expression QueryExpression { get; set; } + 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 override bool CanReduce => false; @@ -52,13 +50,4 @@ public virtual void Print(ExpressionPrinter expressionPrinter) } } } - - public enum ResultType - { -#pragma warning disable SA1602 // Enumeration items should be documented - Enumerable, - Single, - SingleWithDefault -#pragma warning restore SA1602 // Enumeration items should be documented - } } diff --git a/src/EFCore/Query/Pipeline/ShapedQueryOptimizingExpressionVisitors.cs b/src/EFCore/Query/ShapedQueryOptimizer.cs similarity index 86% rename from src/EFCore/Query/Pipeline/ShapedQueryOptimizingExpressionVisitors.cs rename to src/EFCore/Query/ShapedQueryOptimizer.cs index 3f1c132a9aa..ac049c0696a 100644 --- a/src/EFCore/Query/Pipeline/ShapedQueryOptimizingExpressionVisitors.cs +++ b/src/EFCore/Query/ShapedQueryOptimizer.cs @@ -3,7 +3,7 @@ using System.Linq.Expressions; -namespace Microsoft.EntityFrameworkCore.Query.Pipeline +namespace Microsoft.EntityFrameworkCore.Query { public class ShapedQueryOptimizer { diff --git a/src/EFCore/Query/TransparentIdentifier.cs b/src/EFCore/Query/TransparentIdentifier.cs new file mode 100644 index 00000000000..f91be0c19d5 --- /dev/null +++ b/src/EFCore/Query/TransparentIdentifier.cs @@ -0,0 +1,25 @@ +// 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; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public readonly struct TransparentIdentifier + { + [UsedImplicitly] +#pragma warning disable IDE0051 // Remove unused private members + private TransparentIdentifier(TOuter outer, TInner inner) +#pragma warning restore IDE0051 // Remove unused private members + { + Outer = outer; + Inner = inner; + } + + [UsedImplicitly] + public readonly TOuter Outer; + + [UsedImplicitly] + public readonly TInner Inner; + } +} diff --git a/src/EFCore/Storage/DatabaseDependencies.cs b/src/EFCore/Storage/DatabaseDependencies.cs index 033d192991a..d7d21f6a674 100644 --- a/src/EFCore/Storage/DatabaseDependencies.cs +++ b/src/EFCore/Storage/DatabaseDependencies.cs @@ -2,8 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Update; -using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -46,9 +47,14 @@ public sealed class DatabaseDependencies /// 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. + /// /// - /// Factory for compilation contexts to process LINQ queries. - /// Factory for creating model data tracker. + [EntityFrameworkInternal] public DatabaseDependencies( [NotNull] IQueryCompilationContextFactory queryCompilationContextFactory, [NotNull] IUpdateAdapterFactory updateAdapterFactory) diff --git a/src/EFCore/Storage/DatabaseProviderDependencies.cs b/src/EFCore/Storage/DatabaseProviderDependencies.cs index fd8218aa117..d5180fc3001 100644 --- a/src/EFCore/Storage/DatabaseProviderDependencies.cs +++ b/src/EFCore/Storage/DatabaseProviderDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Storage @@ -42,8 +43,14 @@ public sealed class DatabaseProviderDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public DatabaseProviderDependencies() { } diff --git a/src/EFCore/Storage/ExecutionStrategyDependencies.cs b/src/EFCore/Storage/ExecutionStrategyDependencies.cs index 2c800b0b3f6..b4db0b2c1f8 100644 --- a/src/EFCore/Storage/ExecutionStrategyDependencies.cs +++ b/src/EFCore/Storage/ExecutionStrategyDependencies.cs @@ -46,10 +46,14 @@ public sealed class ExecutionStrategyDependencies /// 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. + /// /// - /// Indirection to the current instance. - /// The options for the current instance. - /// A logger. + [EntityFrameworkInternal] public ExecutionStrategyDependencies( [NotNull] ICurrentDbContext currentContext, [CanBeNull] IDbContextOptions options, diff --git a/src/EFCore/Storage/TypeMappingSourceDependencies.cs b/src/EFCore/Storage/TypeMappingSourceDependencies.cs index b0ef393c657..7b1431c1f49 100644 --- a/src/EFCore/Storage/TypeMappingSourceDependencies.cs +++ b/src/EFCore/Storage/TypeMappingSourceDependencies.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -46,9 +47,14 @@ public sealed class TypeMappingSourceDependencies /// 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. + /// /// - /// The registry of known s. - /// The plugins. + [EntityFrameworkInternal] public TypeMappingSourceDependencies( [NotNull] IValueConverterSelector valueConverterSelector, [NotNull] IEnumerable plugins) diff --git a/src/EFCore/Storage/ValueConversion/DefaultValueConverterRegistryDependencies.cs b/src/EFCore/Storage/ValueConversion/DefaultValueConverterRegistryDependencies.cs index 495fe349662..d69183aecbd 100644 --- a/src/EFCore/Storage/ValueConversion/DefaultValueConverterRegistryDependencies.cs +++ b/src/EFCore/Storage/ValueConversion/DefaultValueConverterRegistryDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion @@ -42,8 +43,14 @@ public sealed class ValueConverterSelectorDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public ValueConverterSelectorDependencies() { } diff --git a/src/EFCore/Storage/ValueConversion/Internal/CompositeValueConverter.cs b/src/EFCore/Storage/ValueConversion/Internal/CompositeValueConverter.cs index 46dde71fdc9..a65a7507a07 100644 --- a/src/EFCore/Storage/ValueConversion/Internal/CompositeValueConverter.cs +++ b/src/EFCore/Storage/ValueConversion/Internal/CompositeValueConverter.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Linq.Expressions; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.Pipeline; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal { diff --git a/src/EFCore/ValueGeneration/ValueGeneratorCacheDependencies.cs b/src/EFCore/ValueGeneration/ValueGeneratorCacheDependencies.cs index 5a5f9560dec..0cfdf7ca900 100644 --- a/src/EFCore/ValueGeneration/ValueGeneratorCacheDependencies.cs +++ b/src/EFCore/ValueGeneration/ValueGeneratorCacheDependencies.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.ValueGeneration @@ -42,8 +43,14 @@ public sealed class ValueGeneratorCacheDependencies /// 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. + /// /// - // ReSharper disable once EmptyConstructor + [EntityFrameworkInternal] public ValueGeneratorCacheDependencies() { } diff --git a/src/EFCore/ValueGeneration/ValueGeneratorSelectorDependencies.cs b/src/EFCore/ValueGeneration/ValueGeneratorSelectorDependencies.cs index cbf27c5ecb3..1405c70e881 100644 --- a/src/EFCore/ValueGeneration/ValueGeneratorSelectorDependencies.cs +++ b/src/EFCore/ValueGeneration/ValueGeneratorSelectorDependencies.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -44,8 +45,14 @@ public sealed class ValueGeneratorSelectorDependencies /// 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. + /// /// - /// The cache to be used to store value generator instances. + [EntityFrameworkInternal] public ValueGeneratorSelectorDependencies([NotNull] IValueGeneratorCache cache) { Check.NotNull(cache, nameof(cache)); diff --git a/src/Shared/DictionaryExtensions.cs b/src/Shared/DictionaryExtensions.cs index 26529969b7e..c88bd4a1c08 100644 --- a/src/Shared/DictionaryExtensions.cs +++ b/src/Shared/DictionaryExtensions.cs @@ -5,23 +5,11 @@ using System.Diagnostics; using JetBrains.Annotations; -namespace Microsoft.EntityFrameworkCore.Internal +namespace Microsoft.EntityFrameworkCore.Utilities { - /// - /// 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. - /// [DebuggerStepThrough] internal static class DictionaryExtensions { - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public static TValue GetOrAddNew( [NotNull] this IDictionary source, [NotNull] TKey key) @@ -36,12 +24,6 @@ public static TValue GetOrAddNew( return value; } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public static TValue Find( [NotNull] this IReadOnlyDictionary source, [NotNull] TKey key) diff --git a/src/Shared/DisposableExtensions.cs b/src/Shared/DisposableExtensions.cs index 55300a4a439..1217b8ccc05 100644 --- a/src/Shared/DisposableExtensions.cs +++ b/src/Shared/DisposableExtensions.cs @@ -5,22 +5,10 @@ using System.Threading.Tasks; using JetBrains.Annotations; -namespace Microsoft.EntityFrameworkCore.Internal +namespace Microsoft.EntityFrameworkCore.Utilities { - /// - /// 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. - /// internal static class DisposableExtensions { - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// public static ValueTask DisposeAsyncIfAvailable([CanBeNull] this IDisposable disposable) { if (disposable != null) diff --git a/src/ef/AppDomainOperationExecutor.cs b/src/ef/AppDomainOperationExecutor.cs index 18821c44e4d..df96fee0998 100644 --- a/src/ef/AppDomainOperationExecutor.cs +++ b/src/ef/AppDomainOperationExecutor.cs @@ -8,7 +8,7 @@ using System.IO; using System.Reflection; using Microsoft.EntityFrameworkCore.Design; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Tools.Properties; namespace Microsoft.EntityFrameworkCore.Tools diff --git a/src/ef/ReflectionOperationExecutor.cs b/src/ef/ReflectionOperationExecutor.cs index 7695d052833..716e0f6f0d6 100644 --- a/src/ef/ReflectionOperationExecutor.cs +++ b/src/ef/ReflectionOperationExecutor.cs @@ -6,8 +6,8 @@ using System.Collections.Generic; using System.IO; using System.Reflection; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Tools.Properties; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.Tools { diff --git a/src/ef/ef.csproj b/src/ef/ef.csproj index bd3b7ae0102..9e95985c3b6 100644 --- a/src/ef/ef.csproj +++ b/src/ef/ef.csproj @@ -16,7 +16,7 @@ - + diff --git a/test/EFCore.Relational.Specification.Tests/MigrationSqlGeneratorTestBase.cs b/test/EFCore.Relational.Specification.Tests/MigrationSqlGeneratorTestBase.cs index c6d9b5c4a98..23fb2c284ca 100644 --- a/test/EFCore.Relational.Specification.Tests/MigrationSqlGeneratorTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/MigrationSqlGeneratorTestBase.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; diff --git a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs index bc2a99d8f26..8b49feeb506 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; diff --git a/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs b/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs index 4f8cb54d815..198ee0ec6bb 100644 --- a/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs +++ b/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs @@ -182,7 +182,7 @@ public static int MethodA(string a, int b) throw new NotImplementedException(); } - [DbFunction(Schema = "bar", FunctionName = "MethodFoo")] + [DbFunction(Schema = "bar", Name = "MethodFoo")] public static int MethodB(string c, int d) { throw new NotImplementedException(); @@ -229,8 +229,8 @@ var dup2methodInfo var dbFunc1 = modelBuilder.HasDbFunction(dup1methodInfo).HasName("Dup1").Metadata; var dbFunc2 = modelBuilder.HasDbFunction(dup2methodInfo).HasName("Dup2").Metadata; - Assert.Equal("Dup1", dbFunc1.FunctionName); - Assert.Equal("Dup2", dbFunc2.FunctionName); + Assert.Equal("Dup1", dbFunc1.Name); + Assert.Equal("Dup2", dbFunc2.Name); } [ConditionalFact] @@ -267,7 +267,7 @@ var methodInfo var dbFunc = modelBuilder.HasDbFunction(methodInfo).Metadata; - Assert.Equal("InstancePublicBase", dbFunc.FunctionName); + Assert.Equal("InstancePublicBase", dbFunc.Name); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } @@ -305,7 +305,7 @@ public void Adding_method_fluent_only_convention_defaults() var dbFuncBuilder = modelBuilder.HasDbFunction(MethodAmi); var dbFunc = dbFuncBuilder.Metadata; - Assert.Equal("MethodA", dbFunc.FunctionName); + Assert.Equal("MethodA", dbFunc.Name); Assert.Null(dbFunc.Schema); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } @@ -318,7 +318,7 @@ public void Adding_method_fluent_only_convention_defaults_fluent_method_info() var dbFuncBuilder = modelBuilder.HasDbFunction(() => TestMethods.MethodA(null, default)); var dbFunc = dbFuncBuilder.Metadata; - Assert.Equal("MethodA", dbFunc.FunctionName); + Assert.Equal("MethodA", dbFunc.Name); Assert.Null(dbFunc.Schema); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } @@ -358,7 +358,7 @@ public void Adding_method_fluent_only_with_name_schema() var dbFunc = dbFuncBuilder.Metadata; - Assert.Equal("foo", dbFunc.FunctionName); + Assert.Equal("foo", dbFunc.Name); Assert.Equal("bar", dbFunc.Schema); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } @@ -372,7 +372,7 @@ public void Adding_method_fluent_only_with_builder() var dbFunc = modelBuilder.HasDbFunction(MethodAmi).Metadata; - Assert.Equal("foo", dbFunc.FunctionName); + Assert.Equal("foo", dbFunc.Name); Assert.Equal("bar", dbFunc.Schema); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } @@ -385,7 +385,7 @@ public void Adding_method_with_attribute_only() var dbFuncBuilder = modelBuilder.HasDbFunction(MethodBmi); var dbFunc = dbFuncBuilder.Metadata; - Assert.Equal("MethodFoo", dbFunc.FunctionName); + Assert.Equal("MethodFoo", dbFunc.Name); Assert.Equal("bar", dbFunc.Schema); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } @@ -401,7 +401,7 @@ public void Adding_method_with_attribute_and_fluent_api_configuration_source() var dbFunc = dbFuncBuilder.Metadata; - Assert.Equal("foo", dbFunc.FunctionName); + Assert.Equal("foo", dbFunc.Name); Assert.Equal("bar", dbFunc.Schema); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } @@ -415,7 +415,7 @@ public void Adding_method_with_attribute_and_fluent_configuration_source() var dbFunc = modelBuilder.HasDbFunction(MethodBmi).Metadata; - Assert.Equal("foo", dbFunc.FunctionName); + Assert.Equal("foo", dbFunc.Name); Assert.Equal("bar", dbFunc.Schema); Assert.Equal(typeof(int), dbFunc.MethodInfo.ReturnType); } diff --git a/test/EFCore.Relational.Tests/Metadata/RelationalBuilderExtensionsTest.cs b/test/EFCore.Relational.Tests/Metadata/RelationalBuilderExtensionsTest.cs index 226089c4e6f..64007fa7074 100644 --- a/test/EFCore.Relational.Tests/Metadata/RelationalBuilderExtensionsTest.cs +++ b/test/EFCore.Relational.Tests/Metadata/RelationalBuilderExtensionsTest.cs @@ -1028,7 +1028,7 @@ public void Can_create_dbFunction() var dbFunc = modelBuilder.Model.FindDbFunction(testMethod) as DbFunction; Assert.NotNull(dbFunc); - Assert.Equal("MethodA", dbFunc.FunctionName); + Assert.Equal("MethodA", dbFunc.Name); Assert.Null(dbFunc.Schema); } diff --git a/test/EFCore.Relational.Tests/Metadata/RelationalMetadataExtensionsTest.cs b/test/EFCore.Relational.Tests/Metadata/RelationalMetadataExtensionsTest.cs index e00c57ca23f..db10824b33e 100644 --- a/test/EFCore.Relational.Tests/Metadata/RelationalMetadataExtensionsTest.cs +++ b/test/EFCore.Relational.Tests/Metadata/RelationalMetadataExtensionsTest.cs @@ -382,7 +382,7 @@ public void Can_get_and_set_dbfunction() var dbFunc = model.AddDbFunction(testMethod); Assert.NotNull(dbFunc); - Assert.NotNull(dbFunc.FunctionName); + Assert.NotNull(dbFunc.Name); Assert.Null(dbFunc.Schema); } diff --git a/test/EFCore.Relational.Tests/RelationalMemberTranslatorProviderDependenciesTest.cs b/test/EFCore.Relational.Tests/RelationalMemberTranslatorProviderDependenciesTest.cs new file mode 100644 index 00000000000..a869e28845e --- /dev/null +++ b/test/EFCore.Relational.Tests/RelationalMemberTranslatorProviderDependenciesTest.cs @@ -0,0 +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.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace Microsoft.EntityFrameworkCore +{ + public class RelationalMemberTranslatorProviderDependenciesTest + { + [ConditionalFact] + public void Can_use_With_methods_to_clone_and_replace_service() + { + RelationalTestHelpers.Instance.TestDependenciesClone(); + } + } +} diff --git a/test/EFCore.Relational.Tests/RelationalMethodCallTranslatorProviderDependenciesTest.cs b/test/EFCore.Relational.Tests/RelationalMethodCallTranslatorProviderDependenciesTest.cs new file mode 100644 index 00000000000..a93b095fc94 --- /dev/null +++ b/test/EFCore.Relational.Tests/RelationalMethodCallTranslatorProviderDependenciesTest.cs @@ -0,0 +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.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace Microsoft.EntityFrameworkCore +{ + public class RelationalMethodCallTranslatorProviderDependenciesTest + { + [ConditionalFact] + public void Can_use_With_methods_to_clone_and_replace_service() + { + RelationalTestHelpers.Instance.TestDependenciesClone(); + } + } +} diff --git a/test/EFCore.Relational.Tests/RelationalSqlTranslatingExpressionVisitorFactoryDependenciesTest.cs b/test/EFCore.Relational.Tests/RelationalSqlTranslatingExpressionVisitorFactoryDependenciesTest.cs new file mode 100644 index 00000000000..9f584dc3f67 --- /dev/null +++ b/test/EFCore.Relational.Tests/RelationalSqlTranslatingExpressionVisitorFactoryDependenciesTest.cs @@ -0,0 +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.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace Microsoft.EntityFrameworkCore +{ + public class RelationalSqlTranslatingExpressionVisitorFactoryDependenciesTest + { + [ConditionalFact] + public void Can_use_With_methods_to_clone_and_replace_service() + { + RelationalTestHelpers.Instance.TestDependenciesClone(); + } + } +} diff --git a/test/EFCore.Relational.Tests/SqlExpressionFactoryDependenciesTest.cs b/test/EFCore.Relational.Tests/SqlExpressionFactoryDependenciesTest.cs new file mode 100644 index 00000000000..cb0cc1a3fe9 --- /dev/null +++ b/test/EFCore.Relational.Tests/SqlExpressionFactoryDependenciesTest.cs @@ -0,0 +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.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace Microsoft.EntityFrameworkCore +{ + public class SqlExpressionFactoryDependenciesTest + { + [ConditionalFact] + public void Can_use_With_methods_to_clone_and_replace_service() + { + RelationalTestHelpers.Instance.TestDependenciesClone(); + } + } +} diff --git a/test/EFCore.Specification.Tests/LoggingTestBase.cs b/test/EFCore.Specification.Tests/LoggingTestBase.cs index 9dbe469e05c..ad571e91e98 100644 --- a/test/EFCore.Specification.Tests/LoggingTestBase.cs +++ b/test/EFCore.Specification.Tests/LoggingTestBase.cs @@ -5,6 +5,7 @@ using System.Linq; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.Extensions.DependencyInjection; diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs index e008446554b..45dd2b20b7f 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs @@ -11,12 +11,9 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.TestModels.Northwind; using Microsoft.EntityFrameworkCore.TestUtilities; -using Microsoft.EntityFrameworkCore.TestUtilities.Xunit; using Microsoft.Extensions.Caching.Memory; using Xunit; diff --git a/test/EFCore.Specification.Tests/TestUtilities/AnnotationComparer.cs b/test/EFCore.Specification.Tests/TestUtilities/AnnotationComparer.cs index 00ee6540880..1f4e2536e6d 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/AnnotationComparer.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/AnnotationComparer.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; // ReSharper disable PossibleNullReferenceException diff --git a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/InjectStringFunctionExpressionMutator.cs b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/InjectStringFunctionExpressionMutator.cs index 553ccf318c8..93bb05df2b1 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/InjectStringFunctionExpressionMutator.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/InjectStringFunctionExpressionMutator.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.TestUtilities.QueryTestGeneration { diff --git a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs index 0c3fab24a70..7468e7701f5 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; namespace Microsoft.EntityFrameworkCore.TestUtilities.QueryTestGeneration { diff --git a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/StringConcatWithSelfExpressionMutator.cs b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/StringConcatWithSelfExpressionMutator.cs index 6d9c3a9cf59..1fbdcab9bae 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/StringConcatWithSelfExpressionMutator.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/StringConcatWithSelfExpressionMutator.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.TestUtilities.QueryTestGeneration { diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs index 63e41cda3ae..2e0f0c4d625 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SpatialQuerySqlServerFixture.cs @@ -3,7 +3,7 @@ using System.Linq; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.TestModels.SpatialModel; using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.Extensions.DependencyInjection; diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs b/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs index 0b6c0d1e106..e23522cc5bc 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteFixture.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Sqlite.Storage.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.TestModels.SpatialModel; diff --git a/test/EFCore.Tests/ApiConsistencyTestBase.cs b/test/EFCore.Tests/ApiConsistencyTestBase.cs index b9e77533ecd..225209add5b 100644 --- a/test/EFCore.Tests/ApiConsistencyTestBase.cs +++ b/test/EFCore.Tests/ApiConsistencyTestBase.cs @@ -58,7 +58,6 @@ where sd.ServiceType.Namespace.StartsWith("Microsoft.Entity", StringComparison.O where !it.IsInterface let ns = it.Namespace where ns.StartsWith("Microsoft.Entity", StringComparison.Ordinal) - && !ns.Contains("Query.Pipeline", StringComparison.Ordinal) && !ns.EndsWith(".Internal", StringComparison.Ordinal) && !it.Name.EndsWith("Dependencies", StringComparison.Ordinal) && (it.GetConstructors().Length != 1 @@ -96,7 +95,6 @@ from method in type.GetMethods(AnyInstance) && !method.Name.StartsWith("remove_", StringComparison.Ordinal) && (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly) && method.Name != "GenerateCacheKeyCore" - && !method.DeclaringType.Namespace.Contains("Query.Pipeline", StringComparison.Ordinal) select type.FullName + "." + method.Name) .ToList(); diff --git a/test/EFCore.Tests/DbContextServicesTest.cs b/test/EFCore.Tests/DbContextServicesTest.cs index 60d93e0b9c8..20f6d89e1bc 100644 --- a/test/EFCore.Tests/DbContextServicesTest.cs +++ b/test/EFCore.Tests/DbContextServicesTest.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -17,7 +16,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.EntityFrameworkCore.ValueGeneration; using Microsoft.Extensions.Caching.Memory; @@ -623,6 +621,10 @@ protected internal override void OnModelCreating(ModelBuilder modelBuilder) private class FakeEntityMaterializerSource : EntityMaterializerSource { + public FakeEntityMaterializerSource(EntityMaterializerSourceDependencies dependencies) + : base(dependencies) + { + } } private class FakeModelSource : IModelSource @@ -2612,8 +2614,7 @@ public CustomInMemoryValueGeneratorSelector( private class CustomInMemoryTableFactory : InMemoryTableFactory { - public CustomInMemoryTableFactory( - [NotNull] ILoggingOptions loggingOptions) + public CustomInMemoryTableFactory(ILoggingOptions loggingOptions) : base(loggingOptions) { } diff --git a/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs b/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs index 72be3c61148..98edab497e1 100644 --- a/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs +++ b/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs @@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; diff --git a/test/EFCore.Tests/Metadata/Internal/EntityMaterializerSourceTest.cs b/test/EFCore.Tests/Metadata/Internal/EntityMaterializerSourceTest.cs index fcdc8ce3545..370e08ed351 100644 --- a/test/EFCore.Tests/Metadata/Internal/EntityMaterializerSourceTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/EntityMaterializerSourceTest.cs @@ -8,7 +8,6 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; using Xunit; @@ -40,7 +39,7 @@ public void Can_create_materializer_for_entity_with_constructor_properties() ); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var gu = Guid.NewGuid(); var entity = (SomeEntity)factory( @@ -76,7 +75,7 @@ public void Can_create_materializer_for_entity_with_factory_method() entityType.ClrType); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var gu = Guid.NewGuid(); var entity = (SomeEntity)factory( @@ -116,7 +115,7 @@ public void Can_create_materializer_for_entity_with_factory_method_with_object_a entityType.ClrType); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var gu = Guid.NewGuid(); var entity = (SomeEntity)factory( @@ -152,7 +151,7 @@ public void Can_create_materializer_for_entity_with_instance_factory_method() entityType.ClrType); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var gu = Guid.NewGuid(); var entity = (SomeEntity)factory( @@ -197,7 +196,7 @@ public void Can_create_materializer_for_entity_with_auto_properties() var entityType = CreateEntityType(); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var gu = Guid.NewGuid(); var entity = (SomeEntity)factory( @@ -223,7 +222,7 @@ public void Can_create_materializer_for_entity_with_fields() entityType.AddProperty(SomeEntityWithFields.MaybeEnumProperty).SetField("_maybeEnum"); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var gu = Guid.NewGuid(); var entity = (SomeEntityWithFields)factory( @@ -247,7 +246,7 @@ public void Can_read_nulls() entityType.AddProperty(SomeEntity.IdProperty); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var entity = (SomeEntity)factory( new MaterializationContext( @@ -271,7 +270,7 @@ public void Can_create_materializer_for_entity_ignoring_shadow_fields() entityType.AddProperty("GooShadow", typeof(Guid)); ((Model)entityType.Model).FinalizeModel(); - var factory = GetMaterializer(new EntityMaterializerSource(), entityType); + var factory = GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType); var gu = Guid.NewGuid(); var entity = (SomeEntity)factory( @@ -292,7 +291,7 @@ public void Throws_if_parameterless_constructor_is_not_defined_on_entity_type() Assert.Equal( CoreStrings.NoParameterlessConstructor(typeof(EntityWithoutParameterlessConstructor).Name), - Assert.Throws(() => GetMaterializer(new EntityMaterializerSource(), entityType)).Message); + Assert.Throws(() => GetMaterializer(new EntityMaterializerSource(new EntityMaterializerSourceDependencies()), entityType)).Message); } private static readonly ParameterExpression _contextParameter diff --git a/test/EFCore.Tests/Query/EntityMaterializerSourceDependenciesTest.cs b/test/EFCore.Tests/Query/EntityMaterializerSourceDependenciesTest.cs new file mode 100644 index 00000000000..2ab71c9f696 --- /dev/null +++ b/test/EFCore.Tests/Query/EntityMaterializerSourceDependenciesTest.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 EntityMaterializerSourceDependenciesTest + { + [ConditionalFact] + public void Can_use_With_methods_to_clone_and_replace_service() + { + InMemoryTestHelpers.Instance.TestDependenciesClone(); + } + } +}