[release/6.0] Microsoft.Data.Sqlite: Fix handling of queries with RETURNING clause #31013
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #30851
When using the DELETE journaling mode in SQLite (Note, this is not the default for databases created by EF), the RETURNING clause on INSERT, UPDATE, and DELETE statements exhibits some unusual behavior. It will return results before the changes are actually persisted to the database. Only after consuming the entire DbDataReader (or disposing it) will it report that the table is busy and cannot be updated. This is the first statement we've encountered with this behavior.
This issue fixes a bug where errors encountered while disposing a DbDataReader were being swallowed/ignored by Microsoft.Data.Sqlite.
Customer impact
Two users have reported this issue. Because the error was previously ignored, it appeared to your application that the changes were successfully made to the database when, in fact, they were not. From the application's perspective, this results in changes made by statements with RETURNING clauses occasionally being lost (or not persisted).
The RETURNING clause was added to SQLite in the .NET 6 timeframe, and we started using it in certain cases in .NET 7.
Once users discover that this is an issue, they can work around it in various ways. For example, by using WAL journaling mode (the EF default, and the recommended one), by using shared cache mode, by wrapping the statement inside a transaction, or by using a separate SELECT statement instead of the RETURNING clause.
Regression
No. This bug has always existed but could only be hit by this unusual behavior of the RETURNING clause.
Risk
Low. This just surfaces errors that are already happening to the application via exceptions.
Verification
Automated tests added to verify a "busy" exception is always thrown.
Manually verified that the user-reported scenario using EF Core throws as well.