Skip to content

Instantly share code, notes, and snippets.

@DavidBoike
Last active June 17, 2021 19:06
Show Gist options
  • Save DavidBoike/94a1d5e3fc57e735843a33054e6ba03e to your computer and use it in GitHub Desktop.
Save DavidBoike/94a1d5e3fc57e735843a33054e6ba03e to your computer and use it in GitHub Desktop.
Reproduction for Microsoft.Data.SqlClient deadlocking issue https://github.com/dotnet/SqlClient/issues/1124
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net472</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.3" />
<Reference Include="System.Transactions" />
</ItemGroup>
</Project>
using Microsoft.Data.SqlClient;
using System;
using System.Threading.Tasks;
using System.Transactions;
namespace PrepareFailTest
{
class Program
{
static string connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=master;Integrated Security=True;";
static readonly TransactionOptions transactionOptions = new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadCommitted,
Timeout = TransactionManager.DefaultTimeout
};
public static async Task Main()
{
try
{
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions, TransactionScopeAsyncFlowOption.Enabled))
{
using (var conn = new SqlConnection(connStr))
{
await conn.OpenAsync();
Transaction.Current.EnlistDurable(EnlistmentWhichFailsDuringPrepare.Id, new EnlistmentWhichFailsDuringPrepare(), EnlistmentOptions.None);
scope.Complete();
}
}
}
catch (Exception x)
{
Console.WriteLine(x.Message);
}
Console.WriteLine("Test run complete");
}
}
class EnlistmentWhichFailsDuringPrepare : IEnlistmentNotification
{
public static readonly Guid Id = Guid.NewGuid();
// fail during prepare, this will cause scope.Complete to throw
public void Prepare(PreparingEnlistment preparingEnlistment) => preparingEnlistment.ForceRollback();
public void Commit(Enlistment enlistment) => enlistment.Done();
public void Rollback(Enlistment enlistment) => enlistment.Done();
public void InDoubt(Enlistment enlistment) => enlistment.Done();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment