Fix EF Core 10 API breaking changes in query processor and modification command batch#109
Conversation
Replace obsolete Optimize method with Process method that uses ParametersCacheDecorator instead of IReadOnlyDictionary for parameter handling. Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com>
|
@copilot Do continue to investigate the issue for SaveChanges() and find a solution based on how SQL Server and PostgreSQL and SQLite solves it |
In EF Core 10, ReaderModificationCommandBatch now provides a ParameterValues property. The MySQL provider was maintaining its own _parameterValues dictionary which caused parameter lookup failures during SaveChanges. Changed to use the base class's ParameterValues property instead, following the pattern used by SQL Server, PostgreSQL, and SQLite providers. Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com>
Fixed in commit 2c4520d. The issue was that EF Core 10 added a Changed to use the inherited |
EF Core 10 introduced breaking changes in both the query processor API and the modification command batch system. This PR addresses both issues to ensure compatibility with EF Core 10.
Changes
Query Processor Migration
Optimize()override withProcess()inMySqlParameterBasedSqlProcessorProcessSqlNullability()override for explicit null handling delegationSkipTakeCollapsingExpressionVisitorto acceptParametersCacheDecorator_canCache) withGetAndDisableCaching()callMySqlParameterInliningExpressionVisitorsimilarlycanCacheout parameter fromProcess()signatureModification Command Batch Fix
_parameterValuesdictionary fromMySqlModificationCommandBatchParameterValuesproperty for storing parameter valuesRollbackLastCommandto delegate to base implementationAddParameterCoreto use inheritedParameterValuespropertyRoot Cause
EF Core 10 made two significant changes:
Query Processor: Deprecated
RelationalParameterBasedSqlProcessor.Optimize()in favor ofProcess()withParametersCacheDecoratorfor better query caching controlModification Command Batch: Added a
ParameterValuesproperty to the baseReaderModificationCommandBatchclass. The MySQL provider was maintaining its own_parameterValuesdictionary, but EF Core 10 looks up parameter values from the base class's property, causing "No value was provided for the required parameter" errors during SaveChanges operations.Migration Pattern
Before (EF Core 9):
After (EF Core 10):
Solution
Following the pattern used by SQL Server, PostgreSQL, and SQLite providers in EF Core 10, the MySQL provider now uses the inherited
ParameterValuesproperty from the base class instead of maintaining a separate dictionary.Test Results
Fixes #108
Original prompt
This section details on the original issue you should resolve
<issue_title>Fix failing tests</issue_title>
<issue_description>```
Error: Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while saving the entity changes. See the inner exception for details.
---- System.InvalidOperationException : No value was provided for the required parameter 'p1'.
Failed Pomelo.EntityFrameworkCore.MySql.FunctionalTests.TwoDatabasesMySqlTest.Can_set_connection_string_in_interceptor(withConnectionString: True, withNullConnectionString: True) [982 ms]
[xUnit.net 00:00:14.15] Pomelo.EntityFrameworkCore.MySql.FunctionalTests.TwoDatabasesMySqlTest.Can_set_connection_string_in_interceptor(withConnectionString: True, withNullConnectionString: False) [FAIL]
Error Message:
Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while saving the entity changes. See the inner exception for details.
---- System.InvalidOperationException : No value was provided for the required parameter 'p1'.
Stack Trace:
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable
1 commandBatches, IRelationalConnection connection) at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList1 entries)at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList
1 entriesToSave) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<>c.<SaveChanges>b__114_0(DbContext _, ValueTuple2 t)at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.Execute[TState,TResult](TState state, Func
3 operation, Func3 verifySucceeded) in /home/runner/work/Pomelo.EntityFrameworkCore.MySql/Pomelo.EntityFrameworkCore.MySql/src/EFCore.MySql/Storage/Internal/MySqlExecutionStrategy.cs:line 48at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at Microsoft.EntityFrameworkCore.TwoDatabasesTestBase.Can_set_connection_string_in_interceptor(Boolean withConnectionString, Boolean withNullConnectionString)
at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span
1 copyOfArgs, BindingFlags invokeAttr) ----- Inner Stack Trace ----- at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalParameterBase.AddDbParameter(DbCommand command, IReadOnlyDictionary2 parameterValues)at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.CreateDbCommand(RelationalCommandParameterObject parameterObject, Guid commandId, DbCommandMethod commandMethod)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
[xUnit.net 00:00:14.15] Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while saving the entity changes. See the inner exception for details.
[xUnit.net 00:00:14.15] ---- System.InvalidOperationException : No value was provided for the required parameter 'p1'.
[xUnit.net 00:00:14.15] Stack Trace:
[xUnit.net 00:00:14.15] at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
[xUnit.net 00:00:14.15] at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable
1 commandBatches, IRelationalConnection connection) [xUnit.net 00:00:14.15] at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList1 entries)[xUnit.net 00:00:14.15] at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList
1 entriesToSave) [xUnit.net 00:00:14.15] at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess) [xUnit.net 00:00:14.15] at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<>c.<SaveChanges>b__114_0(DbContext _, ValueTuple2 t)[xUnit.net 00:00:14.15] /home/runner/work/Pomelo.EntityFra...
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.