From 5754cf38f51ae6dededd3daf0893109c2e2e5019 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 17 May 2022 18:06:29 -0700 Subject: [PATCH] Query: Minor refactoring in shaper This is non-breaking change. Next PR will submit potentially breaking changes in RelationalCommandCache area --- .../Internal/FromSqlQueryingEnumerable.cs | 11 ++- .../Query/Internal/RelationalCommandCache.cs | 10 --- .../Internal/SingleQueryingEnumerable.cs | 11 ++- .../Query/Internal/SplitQueryingEnumerable.cs | 11 ++- ...sitor.ShaperProcessingExpressionVisitor.cs | 68 ++++++++++++------- ...alShapedQueryCompilingExpressionVisitor.cs | 6 +- 6 files changed, 74 insertions(+), 43 deletions(-) diff --git a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs index ee51011f8cd..b73fa6e0e9d 100644 --- a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs @@ -16,6 +16,7 @@ public class FromSqlQueryingEnumerable : IEnumerable, IAsyncEnumerable, { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly IReadOnlyList _columnNames; private readonly Func _shaper; private readonly Type _contextType; @@ -33,6 +34,7 @@ public class FromSqlQueryingEnumerable : IEnumerable, IAsyncEnumerable, public FromSqlQueryingEnumerable( RelationalQueryContext relationalQueryContext, RelationalCommandCache relationalCommandCache, + IReadOnlyList? readerColumns, IReadOnlyList columnNames, Func shaper, Type contextType, @@ -42,6 +44,7 @@ public FromSqlQueryingEnumerable( { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; + _readerColumns = readerColumns; _columnNames = columnNames; _shaper = shaper; _contextType = contextType; @@ -144,6 +147,7 @@ private sealed class Enumerator : IEnumerator { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly IReadOnlyList _columnNames; private readonly Func _shaper; private readonly Type _contextType; @@ -161,6 +165,7 @@ public Enumerator(FromSqlQueryingEnumerable queryingEnumerable) { _relationalQueryContext = queryingEnumerable._relationalQueryContext; _relationalCommandCache = queryingEnumerable._relationalCommandCache; + _readerColumns = queryingEnumerable._readerColumns; _columnNames = queryingEnumerable._columnNames; _shaper = queryingEnumerable._shaper; _contextType = queryingEnumerable._contextType; @@ -232,7 +237,7 @@ private static bool InitializeReader(Enumerator enumerator) new RelationalCommandParameterObject( enumerator._relationalQueryContext.Connection, enumerator._relationalQueryContext.ParameterValues, - enumerator._relationalCommandCache.ReaderColumns, + enumerator._readerColumns, enumerator._relationalQueryContext.Context, enumerator._relationalQueryContext.CommandLogger, enumerator._detailedErrorsEnabled, CommandSource.FromSqlQuery)); @@ -262,6 +267,7 @@ private sealed class AsyncEnumerator : IAsyncEnumerator { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly IReadOnlyList _columnNames; private readonly Func _shaper; private readonly Type _contextType; @@ -279,6 +285,7 @@ public AsyncEnumerator(FromSqlQueryingEnumerable queryingEnumerable) { _relationalQueryContext = queryingEnumerable._relationalQueryContext; _relationalCommandCache = queryingEnumerable._relationalCommandCache; + _readerColumns = queryingEnumerable._readerColumns; _columnNames = queryingEnumerable._columnNames; _shaper = queryingEnumerable._shaper; _contextType = queryingEnumerable._contextType; @@ -352,7 +359,7 @@ private static async Task InitializeReaderAsync(AsyncEnumerator enumerator new RelationalCommandParameterObject( enumerator._relationalQueryContext.Connection, enumerator._relationalQueryContext.ParameterValues, - enumerator._relationalCommandCache.ReaderColumns, + enumerator._readerColumns, enumerator._relationalQueryContext.Context, enumerator._relationalQueryContext.CommandLogger, enumerator._detailedErrorsEnabled, CommandSource.FromSqlQuery), diff --git a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs index 06159a7b185..eeb20b20c8d 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs @@ -35,24 +35,14 @@ public RelationalCommandCache( IQuerySqlGeneratorFactory querySqlGeneratorFactory, IRelationalParameterBasedSqlProcessorFactory relationalParameterBasedSqlProcessorFactory, SelectExpression selectExpression, - IReadOnlyList? readerColumns, bool useRelationalNulls) { _memoryCache = memoryCache; _querySqlGeneratorFactory = querySqlGeneratorFactory; _selectExpression = selectExpression; - ReaderColumns = readerColumns; _relationalParameterBasedSqlProcessor = relationalParameterBasedSqlProcessorFactory.Create(useRelationalNulls); } - /// - /// 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? ReaderColumns { 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 diff --git a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs index 96fe8e5dbac..e9e4dea628d 100644 --- a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs @@ -16,6 +16,7 @@ public class SingleQueryingEnumerable : IEnumerable, IAsyncEnumerable, { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly Func _shaper; private readonly Type _contextType; private readonly IDiagnosticsLogger _queryLogger; @@ -32,6 +33,7 @@ public class SingleQueryingEnumerable : IEnumerable, IAsyncEnumerable, public SingleQueryingEnumerable( RelationalQueryContext relationalQueryContext, RelationalCommandCache relationalCommandCache, + IReadOnlyList? readerColumns, Func shaper, Type contextType, bool standAloneStateManager, @@ -40,6 +42,7 @@ public SingleQueryingEnumerable( { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; + _readerColumns = readerColumns; _shaper = shaper; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; @@ -114,6 +117,7 @@ private sealed class Enumerator : IEnumerator { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly Func _shaper; private readonly Type _contextType; private readonly IDiagnosticsLogger _queryLogger; @@ -131,6 +135,7 @@ public Enumerator(SingleQueryingEnumerable queryingEnumerable) { _relationalQueryContext = queryingEnumerable._relationalQueryContext; _relationalCommandCache = queryingEnumerable._relationalCommandCache; + _readerColumns = queryingEnumerable._readerColumns; _shaper = queryingEnumerable._shaper; _contextType = queryingEnumerable._contextType; _queryLogger = queryingEnumerable._queryLogger; @@ -230,7 +235,7 @@ private static bool InitializeReader(Enumerator enumerator) new RelationalCommandParameterObject( enumerator._relationalQueryContext.Connection, enumerator._relationalQueryContext.ParameterValues, - enumerator._relationalCommandCache.ReaderColumns, + enumerator._readerColumns, enumerator._relationalQueryContext.Context, enumerator._relationalQueryContext.CommandLogger, enumerator._detailedErrorsEnabled, @@ -263,6 +268,7 @@ private sealed class AsyncEnumerator : IAsyncEnumerator { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly Func _shaper; private readonly Type _contextType; private readonly IDiagnosticsLogger _queryLogger; @@ -281,6 +287,7 @@ public AsyncEnumerator(SingleQueryingEnumerable queryingEnumerable) { _relationalQueryContext = queryingEnumerable._relationalQueryContext; _relationalCommandCache = queryingEnumerable._relationalCommandCache; + _readerColumns = queryingEnumerable._readerColumns; _shaper = queryingEnumerable._shaper; _contextType = queryingEnumerable._contextType; _queryLogger = queryingEnumerable._queryLogger; @@ -383,7 +390,7 @@ private static async Task InitializeReaderAsync(AsyncEnumerator enumerator new RelationalCommandParameterObject( enumerator._relationalQueryContext.Connection, enumerator._relationalQueryContext.ParameterValues, - enumerator._relationalCommandCache.ReaderColumns, + enumerator._readerColumns, enumerator._relationalQueryContext.Context, enumerator._relationalQueryContext.CommandLogger, enumerator._detailedErrorsEnabled, CommandSource.LinqQuery), diff --git a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs index a033c5ad650..c87544d1120 100644 --- a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs @@ -16,6 +16,7 @@ public class SplitQueryingEnumerable : IEnumerable, IAsyncEnumerable, I { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly Func _shaper; private readonly Action? _relatedDataLoaders; private readonly Func? _relatedDataLoadersAsync; @@ -34,6 +35,7 @@ public class SplitQueryingEnumerable : IEnumerable, IAsyncEnumerable, I public SplitQueryingEnumerable( RelationalQueryContext relationalQueryContext, RelationalCommandCache relationalCommandCache, + IReadOnlyList? readerColumns, Func shaper, Action? relatedDataLoaders, Func? relatedDataLoadersAsync, @@ -44,6 +46,7 @@ public SplitQueryingEnumerable( { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; + _readerColumns = readerColumns; _shaper = shaper; _relatedDataLoaders = relatedDataLoaders; _relatedDataLoadersAsync = relatedDataLoadersAsync; @@ -122,6 +125,7 @@ private sealed class Enumerator : IEnumerator { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly Func _shaper; private readonly Action? _relatedDataLoaders; private readonly Type _contextType; @@ -140,6 +144,7 @@ public Enumerator(SplitQueryingEnumerable queryingEnumerable) { _relationalQueryContext = queryingEnumerable._relationalQueryContext; _relationalCommandCache = queryingEnumerable._relationalCommandCache; + _readerColumns = queryingEnumerable._readerColumns; _shaper = queryingEnumerable._shaper; _relatedDataLoaders = queryingEnumerable._relatedDataLoaders; _contextType = queryingEnumerable._contextType; @@ -226,7 +231,7 @@ private static bool InitializeReader(Enumerator enumerator) new RelationalCommandParameterObject( enumerator._relationalQueryContext.Connection, enumerator._relationalQueryContext.ParameterValues, - enumerator._relationalCommandCache.ReaderColumns, + enumerator._readerColumns, enumerator._relationalQueryContext.Context, enumerator._relationalQueryContext.CommandLogger, enumerator._detailedErrorsEnabled, @@ -271,6 +276,7 @@ private sealed class AsyncEnumerator : IAsyncEnumerator { private readonly RelationalQueryContext _relationalQueryContext; private readonly RelationalCommandCache _relationalCommandCache; + private readonly IReadOnlyList? _readerColumns; private readonly Func _shaper; private readonly Func? _relatedDataLoaders; private readonly Type _contextType; @@ -290,6 +296,7 @@ public AsyncEnumerator(SplitQueryingEnumerable queryingEnumerable) { _relationalQueryContext = queryingEnumerable._relationalQueryContext; _relationalCommandCache = queryingEnumerable._relationalCommandCache; + _readerColumns = queryingEnumerable._readerColumns; _shaper = queryingEnumerable._shaper; _relatedDataLoaders = queryingEnumerable._relatedDataLoadersAsync; _contextType = queryingEnumerable._contextType; @@ -379,7 +386,7 @@ private static async Task InitializeReaderAsync(AsyncEnumerator enumerator new RelationalCommandParameterObject( enumerator._relationalQueryContext.Connection, enumerator._relationalQueryContext.ParameterValues, - enumerator._relationalCommandCache.ReaderColumns, + enumerator._readerColumns, enumerator._relationalQueryContext.Context, enumerator._relationalQueryContext.CommandLogger, enumerator._detailedErrorEnabled, CommandSource.LinqQuery), diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index 7d47b8228c9..b9fca300552 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -205,6 +205,7 @@ private ShaperProcessingExpressionVisitor( public LambdaExpression ProcessShaper( Expression shaperExpression, out RelationalCommandCache? relationalCommandCache, + out IReadOnlyList? readerColumns, out LambdaExpression? relatedDataLoaders, ref int collectionId) { @@ -222,8 +223,8 @@ public LambdaExpression ProcessShaper( _parentVisitor.RelationalDependencies.QuerySqlGeneratorFactory, _parentVisitor.RelationalDependencies.RelationalParameterBasedSqlProcessorFactory, _selectExpression, - _readerColumns, _parentVisitor._useRelationalNulls); + readerColumns = _readerColumns; return Expression.Lambda( result, @@ -248,9 +249,9 @@ public LambdaExpression ProcessShaper( _parentVisitor.RelationalDependencies.QuerySqlGeneratorFactory, _parentVisitor.RelationalDependencies.RelationalParameterBasedSqlProcessorFactory, _selectExpression, - _readerColumns, _parentVisitor._useRelationalNulls) : null; + readerColumns = _readerColumns; return Expression.Lambda( result, @@ -335,9 +336,9 @@ public LambdaExpression ProcessShaper( _parentVisitor.RelationalDependencies.QuerySqlGeneratorFactory, _parentVisitor.RelationalDependencies.RelationalParameterBasedSqlProcessorFactory, _selectExpression, - _readerColumns, _parentVisitor._useRelationalNulls) : null; + readerColumns = _readerColumns; collectionId = _collectionId; @@ -506,7 +507,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _parentVisitor, _resultCoordinatorParameter, _selectExpression, _dataReaderParameter, _resultContextParameter, _readerColumns) - .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _, ref _collectionId); + .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _, out _, ref _collectionId); var entityType = entity.Type; var navigation = includeExpression.Navigation; @@ -592,6 +593,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var innerShaper = innerProcessor.ProcessShaper( relationalSplitCollectionShaperExpression.InnerShaper, out var relationalCommandCache, + out var readerColumns, out var relatedDataLoaders, ref _collectionId); @@ -648,9 +650,10 @@ protected override Expression VisitExtension(Expression extensionExpression) collectionIdConstant, Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), _executionStrategyParameter!, + Expression.Constant(relationalCommandCache), + Expression.Constant(readerColumns, typeof(IReadOnlyList)), Expression.Constant(_detailedErrorsEnabled), _resultCoordinatorParameter, - Expression.Constant(relationalCommandCache), Expression.Constant(childIdentifierLambda.Compile()), Expression.Constant( relationalSplitCollectionShaperExpression.IdentifierValueComparers, @@ -708,7 +711,7 @@ protected override Expression VisitExtension(Expression extensionExpression) _parentVisitor, _resultCoordinatorParameter, _selectExpression, _dataReaderParameter, _resultContextParameter, _readerColumns) - .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _, ref _collectionId); + .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _, out _, ref _collectionId); var navigation = relationalCollectionShaperExpression.Navigation; var collectionAccessor = navigation?.GetCollectionAccessor(); @@ -795,6 +798,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var innerShaper = innerProcessor.ProcessShaper( relationalSplitCollectionShaperExpression.InnerShaper, out var relationalCommandCache, + out var readerColumns, out var relatedDataLoaders, ref _collectionId); @@ -850,9 +854,10 @@ protected override Expression VisitExtension(Expression extensionExpression) collectionIdConstant, Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), _executionStrategyParameter!, + Expression.Constant(relationalCommandCache), + Expression.Constant(readerColumns, typeof(IReadOnlyList)), Expression.Constant(_detailedErrorsEnabled), _resultCoordinatorParameter, - Expression.Constant(relationalCommandCache), Expression.Constant(childIdentifierLambda.Compile()), Expression.Constant( relationalSplitCollectionShaperExpression.IdentifierValueComparers, @@ -1389,9 +1394,10 @@ private static void PopulateSplitIncludeCollection? readerColumns, bool detailedErrorsEnabled, SplitQueryResultCoordinator resultCoordinator, - RelationalCommandCache relationalCommandCache, Func childIdentifier, IReadOnlyList identifierValueComparers, Func innerShaper, @@ -1407,13 +1413,15 @@ private static void PopulateSplitIncludeCollection InitializeReader(tup.Item1, tup.Item2, tup.Item3), + (queryContext, relationalCommandCache, readerColumns, detailedErrorsEnabled), + ((RelationalQueryContext, RelationalCommandCache, IReadOnlyList?, bool) tup) + => InitializeReader(tup.Item1, tup.Item2, tup.Item3, tup.Item4), verifySucceeded: null); static RelationalDataReader InitializeReader( RelationalQueryContext queryContext, RelationalCommandCache relationalCommandCache, + IReadOnlyList? readerColumns, bool detailedErrorsEnabled) { var relationalCommand = relationalCommandCache.RentAndPopulateRelationalCommand(queryContext); @@ -1422,7 +1430,7 @@ static RelationalDataReader InitializeReader( new RelationalCommandParameterObject( queryContext.Connection, queryContext.ParameterValues, - relationalCommandCache.ReaderColumns, + readerColumns, queryContext.Context, queryContext.CommandLogger, detailedErrorsEnabled, CommandSource.LinqQuery)); @@ -1470,9 +1478,10 @@ private static async Task PopulateSplitIncludeCollectionAsync? readerColumns, bool detailedErrorsEnabled, SplitQueryResultCoordinator resultCoordinator, - RelationalCommandCache relationalCommandCache, Func childIdentifier, IReadOnlyList identifierValueComparers, Func innerShaper, @@ -1488,9 +1497,9 @@ private static async Task PopulateSplitIncludeCollectionAsync InitializeReaderAsync(tup.Item1, tup.Item2, tup.Item3, cancellationToken), + (queryContext, relationalCommandCache, readerColumns, detailedErrorsEnabled), + ((RelationalQueryContext, RelationalCommandCache, IReadOnlyList?, bool) tup, CancellationToken cancellationToken) + => InitializeReaderAsync(tup.Item1, tup.Item2, tup.Item3, tup.Item4, cancellationToken), verifySucceeded: null, queryContext.CancellationToken) .ConfigureAwait(false); @@ -1498,6 +1507,7 @@ private static async Task PopulateSplitIncludeCollectionAsync InitializeReaderAsync( RelationalQueryContext queryContext, RelationalCommandCache relationalCommandCache, + IReadOnlyList? readerColumns, bool detailedErrorsEnabled, CancellationToken cancellationToken) { @@ -1507,10 +1517,11 @@ static async Task InitializeReaderAsync( new RelationalCommandParameterObject( queryContext.Connection, queryContext.ParameterValues, - relationalCommandCache.ReaderColumns, + readerColumns, queryContext.Context, queryContext.CommandLogger, - detailedErrorsEnabled, CommandSource.LinqQuery), + detailedErrorsEnabled, + CommandSource.LinqQuery), cancellationToken) .ConfigureAwait(false); } @@ -1714,9 +1725,10 @@ private static void PopulateSplitCollection? readerColumns, bool detailedErrorsEnabled, SplitQueryResultCoordinator resultCoordinator, - RelationalCommandCache relationalCommandCache, Func childIdentifier, IReadOnlyList identifierValueComparers, Func innerShaper, @@ -1729,13 +1741,15 @@ private static void PopulateSplitCollection InitializeReader(tup.Item1, tup.Item2, tup.Item3), + (queryContext, relationalCommandCache, readerColumns, detailedErrorsEnabled), + ((RelationalQueryContext, RelationalCommandCache, IReadOnlyList?, bool) tup) + => InitializeReader(tup.Item1, tup.Item2, tup.Item3, tup.Item4), verifySucceeded: null); static RelationalDataReader InitializeReader( RelationalQueryContext queryContext, RelationalCommandCache relationalCommandCache, + IReadOnlyList? readerColumns, bool detailedErrorsEnabled) { var relationalCommand = relationalCommandCache.RentAndPopulateRelationalCommand(queryContext); @@ -1744,7 +1758,7 @@ static RelationalDataReader InitializeReader( new RelationalCommandParameterObject( queryContext.Connection, queryContext.ParameterValues, - relationalCommandCache.ReaderColumns, + readerColumns, queryContext.Context, queryContext.CommandLogger, detailedErrorsEnabled, CommandSource.LinqQuery)); @@ -1790,9 +1804,10 @@ private static async Task PopulateSplitCollectionAsync? readerColumns, bool detailedErrorsEnabled, SplitQueryResultCoordinator resultCoordinator, - RelationalCommandCache relationalCommandCache, Func childIdentifier, IReadOnlyList identifierValueComparers, Func innerShaper, @@ -1805,9 +1820,9 @@ private static async Task PopulateSplitCollectionAsync InitializeReaderAsync(tup.Item1, tup.Item2, tup.Item3, cancellationToken), + (queryContext, relationalCommandCache, readerColumns, detailedErrorsEnabled), + ((RelationalQueryContext, RelationalCommandCache, IReadOnlyList?, bool) tup, CancellationToken cancellationToken) + => InitializeReaderAsync(tup.Item1, tup.Item2, tup.Item3, tup.Item4, cancellationToken), verifySucceeded: null, queryContext.CancellationToken) .ConfigureAwait(false); @@ -1815,6 +1830,7 @@ private static async Task PopulateSplitCollectionAsync InitializeReaderAsync( RelationalQueryContext queryContext, RelationalCommandCache relationalCommandCache, + IReadOnlyList? readerColumns, bool detailedErrorsEnabled, CancellationToken cancellationToken) { @@ -1824,7 +1840,7 @@ static async Task InitializeReaderAsync( new RelationalCommandParameterObject( queryContext.Connection, queryContext.ParameterValues, - relationalCommandCache.ReaderColumns, + readerColumns, queryContext.Context, queryContext.CommandLogger, detailedErrorsEnabled, diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs index fda7b603f6d..c2e18b64437 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -52,7 +52,8 @@ protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQuery var splitQuery = querySplittingBehavior == QuerySplittingBehavior.SplitQuery; var collectionCount = 0; var shaper = new ShaperProcessingExpressionVisitor(this, selectExpression, _tags, splitQuery, nonComposedFromSql).ProcessShaper( - shapedQueryExpression.ShaperExpression, out var relationalCommandCache, out var relatedDataLoaders, ref collectionCount); + shapedQueryExpression.ShaperExpression, + out var relationalCommandCache, out var readerColumns, out var relatedDataLoaders, ref collectionCount); if (querySplittingBehavior == null && collectionCount > 1) { @@ -65,6 +66,7 @@ protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQuery typeof(FromSqlQueryingEnumerable<>).MakeGenericType(shaper.ReturnType).GetConstructors()[0], Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), Expression.Constant(relationalCommandCache), + Expression.Constant(readerColumns, typeof(IReadOnlyList)), Expression.Constant( selectExpression.Projection.Select(pe => ((ColumnExpression)pe.Expression).Name).ToList(), typeof(IReadOnlyList)), @@ -90,6 +92,7 @@ protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQuery typeof(SplitQueryingEnumerable<>).MakeGenericType(shaper.ReturnType).GetConstructors().Single(), Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), Expression.Constant(relationalCommandCache), + Expression.Constant(readerColumns, typeof(IReadOnlyList)), Expression.Constant(shaper.Compile()), relatedDataLoadersParameter, relatedDataLoadersAsyncParameter, @@ -104,6 +107,7 @@ protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQuery typeof(SingleQueryingEnumerable<>).MakeGenericType(shaper.ReturnType).GetConstructors()[0], Expression.Convert(QueryCompilationContext.QueryContextParameter, typeof(RelationalQueryContext)), Expression.Constant(relationalCommandCache), + Expression.Constant(readerColumns, typeof(IReadOnlyList)), Expression.Constant(shaper.Compile()), Expression.Constant(_contextType), Expression.Constant(