Fix #3736 | Propagate Errors from ExecuteScalar#3912
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses GitHub issue #3736, which reports that ExecuteScalar() swallows server errors that occur after the first result row is returned. This causes transaction "zombification" where the transaction appears to succeed but is actually rolled back by the server, leading to data integrity issues.
Changes:
- Adds result draining logic to
CompleteExecuteScalar()in the synchronous path to ensure error tokens are processed before returning - Adds comprehensive regression tests for the synchronous
ExecuteScalarmethod, including transaction scenarios - Updates the project file to include the new test file
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| SqlCommand.Scalar.cs | Adds a while loop to drain remaining result sets in the non-batch sync path, ensuring error tokens are processed |
| SqlCommandExecuteScalarTest.cs | Adds 4 regression tests covering conversion errors with and without transactions, plus sanity tests for normal functionality |
| Microsoft.Data.SqlClient.ManualTesting.Tests.csproj | Adds reference to the new test file |
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.Scalar.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
benrr101
left a comment
There was a problem hiding this comment.
I think this change needs some work to ensure we're fixing it in sync and async, as well as ensure we're testing what we actually needs to be tested.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.Scalar.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandExecuteScalarTest.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.Scalar.cs
Outdated
Show resolved
Hide resolved
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3912 +/- ##
==========================================
- Coverage 74.93% 0 -74.94%
==========================================
Files 269 0 -269
Lines 43247 0 -43247
==========================================
- Hits 32407 0 -32407
+ Misses 10840 0 -10840
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Backport of PR #3912 (Fix #3736 | Propagate Errors from ExecuteScalar) to release/6.1 branch. Changes: - netcore/netfx SqlCommand.cs: Drain remaining results in CompleteExecuteScalar sync path - netcore/netfx SqlCommand.cs: Remove _batchRPCMode guard in ExecuteScalarUntilEndAsync - MultipleResultsTest.cs: Updated to expect SqlException from ExecuteScalar draining - SqlCommandExecuteScalarTest.cs: New regression tests (sync/async, transactions, multi-result) - ManualTesting.Tests.csproj: Include new test file Fixes #3736
Co-authored-by: paulmedynski <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Description
Fix ExecuteScalar to propagate errors when server sends data followed by error token
Fixes #3736
This PR fixes an issue where
ExecuteScalar()swallows server errors that occur after the first result row is returned. When SQL Server sends data followed by an error token (e.g., a conversion error during WHERE clause evaluation), the error was being silently consumed duringreader.Close()instead of being thrown to the caller.Problem
When executing a query like
SELECT Id FROM tab1 WHERE Val = 12345against a table containing values that can't be converted (e.g., '42-43'), SQL Server:The original code only read the first result and immediately closed the reader. The Close() method consumed the remaining TDS stream (including the error token) but the error was never propagated to the caller.
This caused serious issues in transactional scenarios:
Solution
In CompleteExecuteScalar(), drain all remaining result sets by calling NextResult() until it returns false before closing the reader. This ensures any pending error tokens are processed and thrown as exceptions.
Changes
SqlCommand.Scalar.cs: Added result draining loop in CompleteExecuteScalar() for the sync path
SqlCommandExecuteScalarTest.cs: Added 4 regression tests