From 932d624facf08e5958b09e1eb028e76a9b8a9d6a Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Fri, 8 Mar 2019 15:13:50 -0800 Subject: [PATCH] Fragment translators are boring --- ...ntityFrameworkRelationalServicesBuilder.cs | 4 - .../IExpressionFragmentTranslator.cs | 31 ---- .../Internal/ComparisonTranslator.cs | 146 ------------------ ...alCompositeExpressionFragmentTranslator.cs | 71 --------- ...xpressionFragmentTranslatorDependencies.cs | 51 ------ .../SqlTranslatingExpressionVisitor.cs | 11 -- ...ranslatingExpressionVisitorDependencies.cs | 21 --- .../Query/PipeLine/ComparisonTranslator.cs | 61 ++++++++ .../RelationalMethodCallTranslatorProvider.cs | 3 +- ...lationalSqlTranslatingExpressionVisitor.cs | 1 + .../SqlServerServiceCollectionExtensions.cs | 1 - .../SqliteServiceCollectionExtensions.cs | 1 - 12 files changed, 64 insertions(+), 338 deletions(-) delete mode 100644 src/EFCore.Relational/Query/ExpressionTranslators/IExpressionFragmentTranslator.cs delete mode 100644 src/EFCore.Relational/Query/ExpressionTranslators/Internal/ComparisonTranslator.cs delete mode 100644 src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslator.cs delete mode 100644 src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslatorDependencies.cs create mode 100644 src/EFCore.Relational/Query/PipeLine/ComparisonTranslator.cs diff --git a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs index e18c63254dd..106218e4101 100644 --- a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs +++ b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs @@ -10,7 +10,6 @@ using Microsoft.EntityFrameworkCore.Migrations.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Expressions; -using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators; using Microsoft.EntityFrameworkCore.Query.ExpressionVisitors; using Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; @@ -71,7 +70,6 @@ public static readonly IDictionary RelationalServi { typeof(IShaperCommandContextFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) }, { typeof(IConditionalRemovingExpressionVisitorFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) }, { typeof(ISelectExpressionFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) }, - { typeof(IExpressionFragmentTranslator), new ServiceCharacteristics(ServiceLifetime.Singleton) }, { typeof(ISqlTranslatingExpressionVisitorFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) }, { typeof(IUpdateSqlGenerator), new ServiceCharacteristics(ServiceLifetime.Singleton) }, { typeof(IQuerySqlGeneratorFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) }, @@ -168,7 +166,6 @@ public override EntityFrameworkServicesBuilder TryAddCoreServices() TryAdd(); TryAdd(); TryAdd(); - TryAdd(); TryAdd(); TryAdd(); TryAdd(); @@ -188,7 +185,6 @@ public override EntityFrameworkServicesBuilder TryAddCoreServices() ServiceCollectionMap.GetInfrastructure() .AddDependencySingleton() .AddDependencySingleton() - .AddDependencySingleton() .AddDependencySingleton() .AddDependencySingleton() .AddDependencySingleton() diff --git a/src/EFCore.Relational/Query/ExpressionTranslators/IExpressionFragmentTranslator.cs b/src/EFCore.Relational/Query/ExpressionTranslators/IExpressionFragmentTranslator.cs deleted file mode 100644 index 2fbc8e86c8f..00000000000 --- a/src/EFCore.Relational/Query/ExpressionTranslators/IExpressionFragmentTranslator.cs +++ /dev/null @@ -1,31 +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.Linq.Expressions; -using JetBrains.Annotations; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.EntityFrameworkCore.Query.ExpressionTranslators -{ - /// - /// - /// A LINQ expression translator for arbitrary CLR expression fragments. - /// - /// - /// 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 interface IExpressionFragmentTranslator - { - /// - /// Translates the given expression. - /// - /// The expression. - /// - /// A SQL expression representing the translated expression. - /// - Expression Translate([NotNull] Expression expression); - } -} diff --git a/src/EFCore.Relational/Query/ExpressionTranslators/Internal/ComparisonTranslator.cs b/src/EFCore.Relational/Query/ExpressionTranslators/Internal/ComparisonTranslator.cs deleted file mode 100644 index c32bebc0a77..00000000000 --- a/src/EFCore.Relational/Query/ExpressionTranslators/Internal/ComparisonTranslator.cs +++ /dev/null @@ -1,146 +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.Expressions; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.Internal -{ - /// - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - /// - /// 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 class ComparisonTranslator : IExpressionFragmentTranslator - { - private static readonly Dictionary _operatorMap = new Dictionary - { - { ExpressionType.LessThan, ExpressionType.GreaterThan }, - { ExpressionType.LessThanOrEqual, ExpressionType.GreaterThanOrEqual }, - { ExpressionType.GreaterThan, ExpressionType.LessThan }, - { ExpressionType.GreaterThanOrEqual, ExpressionType.LessThanOrEqual }, - { ExpressionType.Equal, ExpressionType.Equal }, - { ExpressionType.NotEqual, ExpressionType.NotEqual } - }; - - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public virtual Expression Translate(Expression expression) - { - if (expression is BinaryExpression binaryExpression) - { - if (!_operatorMap.ContainsKey(expression.NodeType)) - { - return null; - } - - var leftMethodCall = RemoveNullConditional(binaryExpression.Left) as MethodCallExpression; - var rightConstant = binaryExpression.Right.RemoveConvert() as ConstantExpression; - var translated = TranslateInternal(t => t, expression.NodeType, leftMethodCall, rightConstant); - if (translated != null) - { - return translated; - } - - var leftConstant = binaryExpression.Left.RemoveConvert() as ConstantExpression; - var rightMethodCall = RemoveNullConditional(binaryExpression.Right) as MethodCallExpression; - var translatedReverse = TranslateInternal(t => _operatorMap[t], expression.NodeType, rightMethodCall, leftConstant); - - return translatedReverse; - } - - return null; - } - - private static Expression RemoveNullConditional(Expression expression) - => expression.RemoveConvert() is NullConditionalExpression nullConditionalExpression - ? RemoveNullConditional(nullConditionalExpression.AccessOperation) - : expression; - - private static Expression TranslateInternal( - Func opFunc, - ExpressionType op, - MethodCallExpression methodCall, - ConstantExpression constant) - { - if (methodCall != null - && methodCall.Type == typeof(int) - && constant != null - && constant.Type == typeof(int)) - { - var constantValue = (int)constant.Value; - Expression left = null, right = null; - - if (methodCall.Method.Name == "Compare" - && methodCall.Arguments.Count == 2 - && methodCall.Arguments[0].Type == methodCall.Arguments[1].Type) - { - left = methodCall.Arguments[0]; - right = methodCall.Arguments[1]; - } - else if (methodCall.Method.Name == "CompareTo" - && methodCall.Arguments.Count == 1 - && methodCall.Object != null - && methodCall.Object.Type == methodCall.Arguments[0].Type) - { - left = methodCall.Object; - right = methodCall.Arguments[0]; - } - - if (left != null) - { - if (constantValue == 0) - { - // Compare(strA, strB) > 0 => strA > strB - return new ComparisonExpression(opFunc(op), left, right); - } - - if (constantValue == 1) - { - if (op == ExpressionType.Equal) - { - // Compare(strA, strB) == 1 => strA > strB - return new ComparisonExpression(ExpressionType.GreaterThan, left, right); - } - - if (op == opFunc(ExpressionType.LessThan)) - { - // Compare(strA, strB) < 1 => strA <= strB - return new ComparisonExpression(ExpressionType.LessThanOrEqual, left, right); - } - } - - if (constantValue == -1) - { - if (op == ExpressionType.Equal) - { - // Compare(strA, strB) == -1 => strA < strB - return new ComparisonExpression(ExpressionType.LessThan, left, right); - } - - if (op == opFunc(ExpressionType.GreaterThan)) - { - // Compare(strA, strB) > -1 => strA >= strB - return new ComparisonExpression(ExpressionType.GreaterThanOrEqual, left, right); - } - } - } - } - - return null; - } - } -} diff --git a/src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslator.cs b/src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslator.cs deleted file mode 100644 index 1c10a1f8780..00000000000 --- a/src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslator.cs +++ /dev/null @@ -1,71 +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 System.Linq.Expressions; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.Internal; -using Microsoft.EntityFrameworkCore.Utilities; -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.EntityFrameworkCore.Query.ExpressionTranslators -{ - /// - /// - /// A composite expression fragment translator that dispatches to multiple specialized - /// fragment translators. - /// - /// - /// 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 class RelationalCompositeExpressionFragmentTranslator : IExpressionFragmentTranslator - { - private readonly List _translators - = new List - { - new ComparisonTranslator(), - }; - - /// - /// Initializes a new instance of the this class. - /// - /// Parameter object containing dependencies for this service. - public RelationalCompositeExpressionFragmentTranslator( - [NotNull] RelationalCompositeExpressionFragmentTranslatorDependencies dependencies) - { - Check.NotNull(dependencies, nameof(dependencies)); - } - - /// - /// Translates the given expression. - /// - /// The expression to translate. - /// - /// A SQL expression representing the translated expression. - /// - public virtual Expression Translate(Expression expression) - { - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (var translator in _translators) - { - var result = translator.Translate(expression); - if (result != null) - { - return result; - } - } - - return null; - } - - /// - /// Adds additional translators to the dispatch list. - /// - /// The translators. - protected virtual void AddTranslators([NotNull] IEnumerable translators) - => _translators.InsertRange(0, translators); - } -} diff --git a/src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslatorDependencies.cs b/src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslatorDependencies.cs deleted file mode 100644 index 117e03b0043..00000000000 --- a/src/EFCore.Relational/Query/ExpressionTranslators/RelationalCompositeExpressionFragmentTranslatorDependencies.cs +++ /dev/null @@ -1,51 +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.Extensions.DependencyInjection; - -namespace Microsoft.EntityFrameworkCore.Query.ExpressionTranslators -{ - /// - /// - /// 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 of each service is used by many instances. - /// The implementation must be thread-safe. - /// This service cannot depend on services registered as . - /// - /// - public sealed class RelationalCompositeExpressionFragmentTranslatorDependencies - { - /// - /// - /// 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. - /// - /// - // ReSharper disable once EmptyConstructor - public RelationalCompositeExpressionFragmentTranslatorDependencies() - { - } - } -} diff --git a/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitor.cs index 58d42156745..52c2d1958d4 100644 --- a/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitor.cs @@ -11,7 +11,6 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.Expressions; using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; -using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -41,7 +40,6 @@ private static readonly Dictionary _inverseOpera { ExpressionType.NotEqual, ExpressionType.Equal } }; - private readonly IExpressionFragmentTranslator _compositeExpressionFragmentTranslator; private readonly RelationalQueryModelVisitor _queryModelVisitor; private readonly IRelationalTypeMappingSource _typeMappingSource; private readonly SelectExpression _targetSelectExpression; @@ -70,7 +68,6 @@ public SqlTranslatingExpressionVisitor( Check.NotNull(dependencies, nameof(dependencies)); Check.NotNull(queryModelVisitor, nameof(queryModelVisitor)); - _compositeExpressionFragmentTranslator = dependencies.CompositeExpressionFragmentTranslator; _typeMappingSource = dependencies.TypeMappingSource; _queryModelVisitor = queryModelVisitor; _targetSelectExpression = targetSelectExpression; @@ -98,14 +95,6 @@ public SqlTranslatingExpressionVisitor( /// public override Expression Visit(Expression expression) { - var translatedExpression = _compositeExpressionFragmentTranslator.Translate(expression); - - if (translatedExpression != null - && translatedExpression != expression) - { - return Visit(translatedExpression); - } - // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (expression != null && (expression.NodeType == ExpressionType.Convert diff --git a/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitorDependencies.cs b/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitorDependencies.cs index 67ca231828b..a14f4930e6f 100644 --- a/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitorDependencies.cs +++ b/src/EFCore.Relational/Query/ExpressionVisitors/SqlTranslatingExpressionVisitorDependencies.cs @@ -2,7 +2,6 @@ // 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.ExpressionTranslators; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -51,39 +50,20 @@ public sealed class SqlTranslatingExpressionVisitorDependencies /// the constructor at any point in this process. /// /// - /// The composite expression fragment translator. /// The type mapper. public SqlTranslatingExpressionVisitorDependencies( - [NotNull] IExpressionFragmentTranslator compositeExpressionFragmentTranslator, [NotNull] IRelationalTypeMappingSource typeMappingSource) { - Check.NotNull(compositeExpressionFragmentTranslator, nameof(compositeExpressionFragmentTranslator)); Check.NotNull(typeMappingSource, nameof(typeMappingSource)); - CompositeExpressionFragmentTranslator = compositeExpressionFragmentTranslator; TypeMappingSource = typeMappingSource; } - /// - /// The composite expression fragment translator. - /// - public IExpressionFragmentTranslator CompositeExpressionFragmentTranslator { get; } - /// /// 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 SqlTranslatingExpressionVisitorDependencies With([NotNull] IExpressionFragmentTranslator compositeExpressionFragmentTranslator) - => new SqlTranslatingExpressionVisitorDependencies( - compositeExpressionFragmentTranslator, - TypeMappingSource); - /// /// Clones this dependency parameter object with one service replaced. /// @@ -91,7 +71,6 @@ public SqlTranslatingExpressionVisitorDependencies With([NotNull] IExpressionFra /// A new parameter object with the given service replaced. public SqlTranslatingExpressionVisitorDependencies With([NotNull] IRelationalTypeMappingSource typeMappingSource) => new SqlTranslatingExpressionVisitorDependencies( - CompositeExpressionFragmentTranslator, typeMappingSource); } } diff --git a/src/EFCore.Relational/Query/PipeLine/ComparisonTranslator.cs b/src/EFCore.Relational/Query/PipeLine/ComparisonTranslator.cs new file mode 100644 index 00000000000..7de02c7acea --- /dev/null +++ b/src/EFCore.Relational/Query/PipeLine/ComparisonTranslator.cs @@ -0,0 +1,61 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; + +namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline +{ + public class ComparisonTranslator : IMethodCallTranslator + { + private readonly ISqlExpressionFactory _sqlExpressionFactory; + + public ComparisonTranslator(ISqlExpressionFactory sqlExpressionFactory) + { + _sqlExpressionFactory = sqlExpressionFactory; + } + + public SqlExpression Translate(SqlExpression instance, MethodInfo method, IList arguments) + { + if (method.ReturnType == typeof(int)) + { + SqlExpression left = null; + SqlExpression right = null; + if (method.Name == nameof(string.Compare) + && arguments.Count == 2 + && arguments[0].Type.UnwrapNullableType() == arguments[1].Type.UnwrapNullableType()) + { + left = arguments[0]; + right = arguments[1]; + } + else if (method.Name == nameof(string.CompareTo) + && arguments.Count == 1 + && instance != null + && instance.Type.UnwrapNullableType() == arguments[0].Type.UnwrapNullableType()) + { + left = instance; + right = arguments[0]; + } + + if (left != null && right != null) + { + return _sqlExpressionFactory.Case( + new CaseWhenClause[] + { + new CaseWhenClause( + _sqlExpressionFactory.Equal(left, right), _sqlExpressionFactory.Constant(0)), + new CaseWhenClause( + _sqlExpressionFactory.GreaterThan(left, right), _sqlExpressionFactory.Constant(1)), + new CaseWhenClause( + _sqlExpressionFactory.LessThan(left, right), _sqlExpressionFactory.Constant(-1)), + }, + null); + } + } + + return null; + } + } +} diff --git a/src/EFCore.Relational/Query/PipeLine/RelationalMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/PipeLine/RelationalMethodCallTranslatorProvider.cs index 499d6403ac5..13487a79f26 100644 --- a/src/EFCore.Relational/Query/PipeLine/RelationalMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/PipeLine/RelationalMethodCallTranslatorProvider.cs @@ -28,7 +28,8 @@ public RelationalMethodCallTranslatorProvider( new ContainsTranslator(sqlExpressionFactory), new LikeTranslator(sqlExpressionFactory), new EnumHasFlagTranslator(sqlExpressionFactory), - new GetValueOrDefaultTranslator(sqlExpressionFactory) + new GetValueOrDefaultTranslator(sqlExpressionFactory), + new ComparisonTranslator(sqlExpressionFactory), }); _sqlExpressionFactory = sqlExpressionFactory; } diff --git a/src/EFCore.Relational/Query/PipeLine/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/PipeLine/RelationalSqlTranslatingExpressionVisitor.cs index 540727aeb0b..9e057c5a4d7 100644 --- a/src/EFCore.Relational/Query/PipeLine/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/PipeLine/RelationalSqlTranslatingExpressionVisitor.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; diff --git a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs index ec69b071366..9221309b24f 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs @@ -8,7 +8,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators; using Microsoft.EntityFrameworkCore.Query.ExpressionVisitors; using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Query.Sql; diff --git a/src/EFCore.Sqlite.Core/Infrastructure/SqliteServiceCollectionExtensions.cs b/src/EFCore.Sqlite.Core/Infrastructure/SqliteServiceCollectionExtensions.cs index aeb1ad2d107..c61956aa6f7 100644 --- a/src/EFCore.Sqlite.Core/Infrastructure/SqliteServiceCollectionExtensions.cs +++ b/src/EFCore.Sqlite.Core/Infrastructure/SqliteServiceCollectionExtensions.cs @@ -8,7 +8,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators; using Microsoft.EntityFrameworkCore.Query.ExpressionVisitors; using Microsoft.EntityFrameworkCore.Query.Sql; using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline;