diff --git a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs index f4810a2e869..eb2913e2c03 100644 --- a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs @@ -196,7 +196,7 @@ public bool MoveNext() if (_dataReader == null) { _relationalQueryContext.ExecutionStrategyFactory.Create() - .Execute(true, InitializeReader, null); + .Execute(this, (_, enumerator) => InitializeReader(enumerator), null); } var hasNext = _dataReader!.Read(); @@ -220,26 +220,27 @@ public bool MoveNext() } } - private bool InitializeReader(DbContext _, bool result) + private static bool InitializeReader(Enumerator enumerator) { EntityFrameworkEventSource.Log.QueryExecuting(); - var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues); + var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand( + enumerator._relationalQueryContext.ParameterValues); - _dataReader = relationalCommand.ExecuteReader( + enumerator._dataReader = relationalCommand.ExecuteReader( new RelationalCommandParameterObject( - _relationalQueryContext.Connection, - _relationalQueryContext.ParameterValues, - _relationalCommandCache.ReaderColumns, - _relationalQueryContext.Context, - _relationalQueryContext.CommandLogger, - _detailedErrorsEnabled)); + enumerator._relationalQueryContext.Connection, + enumerator._relationalQueryContext.ParameterValues, + enumerator._relationalCommandCache.ReaderColumns, + enumerator._relationalQueryContext.Context, + enumerator._relationalQueryContext.CommandLogger, + enumerator._detailedErrorsEnabled)); - _indexMap = BuildIndexMap(_columnNames, _dataReader.DbDataReader); + enumerator._indexMap = BuildIndexMap(enumerator._columnNames, enumerator._dataReader.DbDataReader); - _relationalQueryContext.InitializeStateManager(_standAloneStateManager); + enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager); - return result; + return false; } public void Dispose() @@ -297,7 +298,11 @@ public async ValueTask MoveNextAsync() if (_dataReader == null) { await _relationalQueryContext.ExecutionStrategyFactory.Create() - .ExecuteAsync(true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken) + .ExecuteAsync( + this, + (_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken), + null, + _relationalQueryContext.CancellationToken) .ConfigureAwait(false); } @@ -322,28 +327,29 @@ await _relationalQueryContext.ExecutionStrategyFactory.Create() } } - private async Task InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken) + private static async Task InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken) { EntityFrameworkEventSource.Log.QueryExecuting(); - var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues); + var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand( + enumerator._relationalQueryContext.ParameterValues); - _dataReader = await relationalCommand.ExecuteReaderAsync( + enumerator._dataReader = await relationalCommand.ExecuteReaderAsync( new RelationalCommandParameterObject( - _relationalQueryContext.Connection, - _relationalQueryContext.ParameterValues, - _relationalCommandCache.ReaderColumns, - _relationalQueryContext.Context, - _relationalQueryContext.CommandLogger, - _detailedErrorsEnabled), + enumerator._relationalQueryContext.Connection, + enumerator._relationalQueryContext.ParameterValues, + enumerator._relationalCommandCache.ReaderColumns, + enumerator._relationalQueryContext.Context, + enumerator._relationalQueryContext.CommandLogger, + enumerator._detailedErrorsEnabled), cancellationToken) .ConfigureAwait(false); - _indexMap = BuildIndexMap(_columnNames, _dataReader.DbDataReader); + enumerator._indexMap = BuildIndexMap(enumerator._columnNames, enumerator._dataReader.DbDataReader); - _relationalQueryContext.InitializeStateManager(_standAloneStateManager); + enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager); - return result; + return false; } public ValueTask DisposeAsync() diff --git a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs index f292593e818..404eaaa50d4 100644 --- a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs @@ -163,7 +163,7 @@ public bool MoveNext() if (_dataReader == null) { _relationalQueryContext.ExecutionStrategyFactory.Create() - .Execute(true, InitializeReader, null); + .Execute(this, (_, enumerator) => InitializeReader(enumerator), null); } var hasNext = _resultCoordinator!.HasNext ?? _dataReader!.Read(); @@ -214,26 +214,27 @@ public bool MoveNext() } } - private bool InitializeReader(DbContext _, bool result) + private static bool InitializeReader(Enumerator enumerator) { EntityFrameworkEventSource.Log.QueryExecuting(); - var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues); + var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand( + enumerator._relationalQueryContext.ParameterValues); - _dataReader = relationalCommand.ExecuteReader( + enumerator._dataReader = relationalCommand.ExecuteReader( new RelationalCommandParameterObject( - _relationalQueryContext.Connection, - _relationalQueryContext.ParameterValues, - _relationalCommandCache.ReaderColumns, - _relationalQueryContext.Context, - _relationalQueryContext.CommandLogger, - _detailedErrorsEnabled)); + enumerator._relationalQueryContext.Connection, + enumerator._relationalQueryContext.ParameterValues, + enumerator._relationalCommandCache.ReaderColumns, + enumerator._relationalQueryContext.Context, + enumerator._relationalQueryContext.CommandLogger, + enumerator._detailedErrorsEnabled)); - _resultCoordinator = new SingleQueryResultCoordinator(); + enumerator._resultCoordinator = new SingleQueryResultCoordinator(); - _relationalQueryContext.InitializeStateManager(_standAloneStateManager); + enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager); - return result; + return false; } public void Dispose() @@ -289,7 +290,11 @@ public async ValueTask MoveNextAsync() if (_dataReader == null) { await _relationalQueryContext.ExecutionStrategyFactory.Create() - .ExecuteAsync(true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken) + .ExecuteAsync( + this, + (_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken), + null, + _relationalQueryContext.CancellationToken) .ConfigureAwait(false); } @@ -342,28 +347,29 @@ await _relationalQueryContext.ExecutionStrategyFactory.Create() } } - private async Task InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken) + private static async Task InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken) { EntityFrameworkEventSource.Log.QueryExecuting(); - var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues); + var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand( + enumerator._relationalQueryContext.ParameterValues); - _dataReader = await relationalCommand.ExecuteReaderAsync( + enumerator._dataReader = await relationalCommand.ExecuteReaderAsync( new RelationalCommandParameterObject( - _relationalQueryContext.Connection, - _relationalQueryContext.ParameterValues, - _relationalCommandCache.ReaderColumns, - _relationalQueryContext.Context, - _relationalQueryContext.CommandLogger, - _detailedErrorsEnabled), + enumerator._relationalQueryContext.Connection, + enumerator._relationalQueryContext.ParameterValues, + enumerator._relationalCommandCache.ReaderColumns, + enumerator._relationalQueryContext.Context, + enumerator._relationalQueryContext.CommandLogger, + enumerator._detailedErrorsEnabled), cancellationToken) .ConfigureAwait(false); - _resultCoordinator = new SingleQueryResultCoordinator(); + enumerator._resultCoordinator = new SingleQueryResultCoordinator(); - _relationalQueryContext.InitializeStateManager(_standAloneStateManager); + enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager); - return result; + return false; } public ValueTask DisposeAsync() diff --git a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs index 906ed8e3c6a..29bbfb8dbe5 100644 --- a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs @@ -177,7 +177,7 @@ public bool MoveNext() _executionStrategy = _relationalQueryContext.ExecutionStrategyFactory.Create(); } - _executionStrategy.Execute(true, InitializeReader, null); + _executionStrategy.Execute(this, (_, enumerator) => InitializeReader(enumerator), null); } var hasNext = _dataReader!.Read(); @@ -208,26 +208,27 @@ public bool MoveNext() } } - private bool InitializeReader(DbContext _, bool result) + private static bool InitializeReader(Enumerator enumerator) { EntityFrameworkEventSource.Log.QueryExecuting(); - var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues); + var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand( + enumerator._relationalQueryContext.ParameterValues); - _dataReader = relationalCommand.ExecuteReader( + enumerator._dataReader = relationalCommand.ExecuteReader( new RelationalCommandParameterObject( - _relationalQueryContext.Connection, - _relationalQueryContext.ParameterValues, - _relationalCommandCache.ReaderColumns, - _relationalQueryContext.Context, - _relationalQueryContext.CommandLogger, - _detailedErrorsEnabled)); + enumerator._relationalQueryContext.Connection, + enumerator._relationalQueryContext.ParameterValues, + enumerator._relationalCommandCache.ReaderColumns, + enumerator._relationalQueryContext.Context, + enumerator._relationalQueryContext.CommandLogger, + enumerator._detailedErrorsEnabled)); - _resultCoordinator = new SplitQueryResultCoordinator(); + enumerator._resultCoordinator = new SplitQueryResultCoordinator(); - _relationalQueryContext.InitializeStateManager(_standAloneStateManager); + enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager); - return result; + return false; } public void Dispose() @@ -303,7 +304,11 @@ public async ValueTask MoveNextAsync() } await _executionStrategy.ExecuteAsync( - true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken).ConfigureAwait(false); + this, + (_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken), + null, + _relationalQueryContext.CancellationToken) + .ConfigureAwait(false); } var hasNext = await _dataReader!.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false); @@ -339,28 +344,29 @@ await _relatedDataLoaders(_relationalQueryContext, _executionStrategy!, _resultC } } - private async Task InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken) + private static async Task InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken) { EntityFrameworkEventSource.Log.QueryExecuting(); - var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues); + var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand( + enumerator._relationalQueryContext.ParameterValues); - _dataReader = await relationalCommand.ExecuteReaderAsync( + enumerator._dataReader = await relationalCommand.ExecuteReaderAsync( new RelationalCommandParameterObject( - _relationalQueryContext.Connection, - _relationalQueryContext.ParameterValues, - _relationalCommandCache.ReaderColumns, - _relationalQueryContext.Context, - _relationalQueryContext.CommandLogger, - _detailedErrorEnabled), + enumerator._relationalQueryContext.Connection, + enumerator._relationalQueryContext.ParameterValues, + enumerator._relationalCommandCache.ReaderColumns, + enumerator._relationalQueryContext.Context, + enumerator._relationalQueryContext.CommandLogger, + enumerator._detailedErrorEnabled), cancellationToken) .ConfigureAwait(false); - _resultCoordinator = new SplitQueryResultCoordinator(); + enumerator._resultCoordinator = new SplitQueryResultCoordinator(); - _relationalQueryContext.InitializeStateManager(_standAloneStateManager); + enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager); - return result; + return false; } public async ValueTask DisposeAsync() diff --git a/src/EFCore/ChangeTracking/Internal/StateManager.cs b/src/EFCore/ChangeTracking/Internal/StateManager.cs index ade7828ded5..e84604fe5b8 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManager.cs @@ -1134,17 +1134,20 @@ protected virtual async Task SaveChangesAsync( /// public virtual int SaveChanges(bool acceptAllChangesOnSuccess) => Context.Database.AutoTransactionsEnabled - ? Dependencies.ExecutionStrategyFactory.Create().Execute(acceptAllChangesOnSuccess, SaveChanges, null) - : SaveChanges(Context, acceptAllChangesOnSuccess); + ? Dependencies.ExecutionStrategyFactory.Create().Execute( + (StateManager: this, AcceptAllChangesOnSuccess: acceptAllChangesOnSuccess), + (_, t) => SaveChanges(t.StateManager, t.AcceptAllChangesOnSuccess), + null) + : SaveChanges(this, acceptAllChangesOnSuccess); - private int SaveChanges(DbContext _, bool acceptAllChangesOnSuccess) + private static int SaveChanges(StateManager stateManager, bool acceptAllChangesOnSuccess) { - if (ChangedCount == 0) + if (stateManager.ChangedCount == 0) { return 0; } - var entriesToSave = GetEntriesToSave(cascadeChanges: true); + var entriesToSave = stateManager.GetEntriesToSave(cascadeChanges: true); if (entriesToSave.Count == 0) { return 0; @@ -1152,8 +1155,8 @@ private int SaveChanges(DbContext _, bool acceptAllChangesOnSuccess) try { - SavingChanges = true; - var result = SaveChanges(entriesToSave); + stateManager.SavingChanges = true; + var result = stateManager.SaveChanges(entriesToSave); if (acceptAllChangesOnSuccess) { @@ -1173,7 +1176,7 @@ private int SaveChanges(DbContext _, bool acceptAllChangesOnSuccess) } finally { - SavingChanges = false; + stateManager.SavingChanges = false; } } @@ -1188,20 +1191,23 @@ public virtual Task SaveChangesAsync( CancellationToken cancellationToken = default) => Context.Database.AutoTransactionsEnabled ? Dependencies.ExecutionStrategyFactory.Create().ExecuteAsync( - acceptAllChangesOnSuccess, SaveChangesAsync, null, cancellationToken) - : SaveChangesAsync(Context, acceptAllChangesOnSuccess, cancellationToken); - - private async Task SaveChangesAsync( - DbContext _, + (StateManager: this, AcceptAllChangesOnSuccess: acceptAllChangesOnSuccess), + (_, t, cancellationToken) => SaveChangesAsync(t.StateManager, t.AcceptAllChangesOnSuccess, cancellationToken), + null, + cancellationToken) + : SaveChangesAsync(this, acceptAllChangesOnSuccess, cancellationToken); + + private static async Task SaveChangesAsync( + StateManager stateManager, bool acceptAllChangesOnSuccess, CancellationToken cancellationToken) { - if (ChangedCount == 0) + if (stateManager.ChangedCount == 0) { return 0; } - var entriesToSave = GetEntriesToSave(cascadeChanges: true); + var entriesToSave = stateManager.GetEntriesToSave(cascadeChanges: true); if (entriesToSave.Count == 0) { return 0; @@ -1209,8 +1215,8 @@ private async Task SaveChangesAsync( try { - SavingChanges = true; - var result = await SaveChangesAsync(entriesToSave, cancellationToken) + stateManager.SavingChanges = true; + var result = await stateManager.SaveChangesAsync(entriesToSave, cancellationToken) .ConfigureAwait(acceptAllChangesOnSuccess); if (acceptAllChangesOnSuccess) @@ -1231,7 +1237,7 @@ private async Task SaveChangesAsync( } finally { - SavingChanges = false; + stateManager.SavingChanges = false; } }