Repository: dotnet/efcore
File: test/EFCore.Relational.Tests/RelationalConnectionTest.cs (C#)

Code before:
                Assert.Equal(RelationalEventId.ConnectionCanceled.Name, d.Item1);
                var eventData = (ConnectionEndEventData)d.Item2;
                Assert.Same(connection.DbConnection, eventData.Connection);
                Assert.True(eventData.IsAsync);
            });
    }

    [ConditionalFact]
    public async Task HandleTransactionCompleted_with_concurrent_ClearTransactions_is_thread_safe()
    {
        // This test verifies the fix for the race condition where HandleTransactionCompleted
        // could be called on a different thread while ClearTransactions is executing.

        // Test with scope.Complete() before ResetState()
        for (var i = 0; i < Environment.ProcessorCount; i++)
        {
            var connection = new FakeRelationalConnection(
                CreateOptions(new FakeRelationalOptionsExtension().WithConnectionString("Database=ConcurrencyTest")));

            var scope = new TransactionScope();
            connection.Open();
            scope.Complete();

            // Start the reset task first, which will yield and then try to reset
            var resetTask = Task.Run(() =>
            {
                // ResetState calls ClearTransactions which might race with HandleTransactionCompleted
                ((IResettableService)connection).ResetState();
            });

            // Dispose the scope on the main thread, which will trigger the TransactionCompleted event
            // The event handler (HandleTransactionCompleted) may execute on a different thread and race
            // with the ClearTransactions call in resetTask
            scope.Dispose();

            await resetTask;
        }

        // Test with ResetState() before scope.Complete()
        for (var i = 0; i < Environment.ProcessorCount; i++)
        {
            var connection = new FakeRelationalConnection(
                CreateOptions(new FakeRelationalOptionsExtension().WithConnectionString("Database=ConcurrencyTest")));

            var scope = new TransactionScope();
            connection.Open();

            // Start the reset task first
            var resetTask = Task.Run(async () =>
            {
                // Small delay to increase chance of race condition

Review comment (bug):
In the first test loop, the resetTask uses a synchronous lambda with no delay, which may not reliably create a race condition. The second loop uses an async lambda with `await Task.Yield()` to introduce timing variance. Consider adding `await Task.Yield()` to the first loop's resetTask as well for consistency and to better ensure the race condition is exercised.
```suggestion
            var resetTask = Task.Run(async () =>
            {
                await Task.Yield();
```

Code after:
                Assert.Equal(RelationalEventId.ConnectionCanceled.Name, d.Item1);
                var eventData = (ConnectionEndEventData)d.Item2;
                Assert.Same(connection.DbConnection, eventData.Connection);
                Assert.True(eventData.IsAsync);
            });
    }

    [ConditionalFact]
    public async Task HandleTransactionCompleted_with_concurrent_ClearTransactions_is_thread_safe()
    {
        // This test verifies the fix for the race condition where HandleTransactionCompleted
        // could be called on a different thread while ClearTransactions is executing.

        // Test with scope.Complete() before ResetState()
        for (var i = 0; i < Environment.ProcessorCount; i++)
        {
            var connection = new FakeRelationalConnection(
                CreateOptions(new FakeRelationalOptionsExtension().WithConnectionString("Database=ConcurrencyTest")));

            var scope = new TransactionScope();
            connection.Open();
            scope.Complete();

            // Start the reset task first, which will yield and then try to reset
            var resetTask = Task.Run(async () =>
            {
                await Task.Yield();
                // ResetState calls ClearTransactions which might race with HandleTransactionCompleted
                ((IResettableService)connection).ResetState();
            });

            // Dispose the scope on the main thread, which will trigger the TransactionCompleted event
            // The event handler (HandleTransactionCompleted) may execute on a different thread and race
            // with the ClearTransactions call in resetTask
            scope.Dispose();

            await resetTask;
        }

        // Test with ResetState() before scope.Complete()
        for (var i = 0; i < Environment.ProcessorCount; i++)
        {
            var connection = new FakeRelationalConnection(
                CreateOptions(new FakeRelationalOptionsExtension().WithConnectionString("Database=ConcurrencyTest")));

            var scope = new TransactionScope();
            connection.Open();

            // Start the reset task first
            var resetTask = Task.Run(async () =>
            {