-
Notifications
You must be signed in to change notification settings - Fork 317
Description
Describe the bug
We have encountered an issue in production where ExecuteScalar run in context of a RepeatableRead transaction intermittently fails to raise an exception when SQL Server selects it as a deadlock victim and rolls back the transaction. The transaction state is correctly set to Aborted, but the lack of an exception confuses application code and libraries like EF Core and who assume (fairly reasonably) that no exception means success.
Additionally, ExecuteScalar is returning the value that would be expected for a successful transaction even though the transaction has been rolled back.
The issue does not seem to occur when using ExecuteReader or ExecuteNonQuery.
I have a reduced repro case which consistently reproduces the error on SQL Server 12 and 13, tested across multiple machines. The issue reproduces with System.Data.SqlClient/dotnet core 2.1 and Microsoft.Data.SqlClient/dotnet core 3.1.
To reproduce
-
Clone the repository https://github.com/deadalusai/SqlClient-Aborted-Transaction-Repro
-
Create a new database using the
ZombieDb.sqlscript -
Run the test program:
For .NET Core 3.1 with Microsoft.Data.SqlClient:
> dotnet run -p .\ZombieTester.NET31.csprojFor .NET Core 2.1 with System.Data.SqlClient:
> dotnet run -p .\ZombieTester.NET21.csproj -
Press any key to start testing for the error case. The test will run until it reproduces the issue or times out.
Expected behavior
A SqlException to be raised when a command is selected as a deadlock victim.
Further technical details
Microsoft.Data.SqlClient version: 1.1.1
System.Data.SqlClient version: 4.8.1
.NET target: .NET Core 3.1, .NET Core 2.1
SQL Server version: SQL Server 2017, SQL Server 2016
Operating system: Windows 10