While testing the .net core 2.1 implementation of TransactionScope I ran into the following issue.
We have a library that configures settings for DB Connections and Transaction scope (Data.Core). Other libraries call this library to execute queries using dapper.
When I execute the code without the debugger, everything runs fine. When I set a breakpoint in the unit test AND also in the method where the DB connection is opened. I then get the exception below.
Any ideas?
System.PlatformNotSupportedException
HResult=0x80131539
Message=This platform does not support distributed transactions.
Source=System.Transactions.Local
StackTrace:
at System.Transactions.Distributed.DistributedTransactionManager.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
at System.Transactions.TransactionInterop.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
at System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
at System.Transactions.Transaction.Promote()
at System.Transactions.TransactionInterop.ConvertToDistributedTransaction(Transaction transaction)
at System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts)
at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Data.Core.DataStore.get_Connection() in D:\TestApps\Repro\Debugger.Issue\Data.Core\DataStore.cs:line 37
at Data.Core.Tests.ReproTest1.TestMethod1() in D:\TestApps\Repro\Debugger.Issue\Data.Core.Tests\ReproTest1.cs:line 14
This is the test method in Data.Core.Tests:
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Data.Core.Tests
{
[TestClass]
public class ReproTest1
{
[TestMethod]
public void TestMethod1()
{
DataStore ds = new DataStore();
using (var scope = ds.BeginTransactionScope())
{
// Set breakpoint on the following line. 1 of 2 breakpoints.
var conn = ds.Connection;
// The following will never be executed in debug
// Run raw ADO.NET command in the transaction
var command = conn.CreateCommand();
command.CommandText = "DELETE FROM dbo.SomeTable";
command.ExecuteNonQuery();
}
}
}
}
This is DataStore class:
using System;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Transactions;
namespace Data.Core
{
using IsolationLevel = System.Transactions.IsolationLevel;
public class DataStore
{
public DataStore()
{
this.DatabaseConnectionString = "Data Source=.;Initial Catalog=SomeDB;Integrated Security=True";
}
/// <summary>
/// Gets or sets the database connection string used to create the database connection.
/// This cannot be null.
/// </summary>
private string DatabaseConnectionString { get; set; }
/// <summary>
/// Gets the connection.
/// </summary>
public SqlConnection Connection
{
get
{
// Set breakpoint on the following line. 2 of 2 breakpoints.
var connection = new SqlConnection(this.DatabaseConnectionString);
if (connection.State != ConnectionState.Open)
{
// This line will throw exception
connection.Open();
}
// See if we need to join an existing transaction scope
if (Transaction.Current != null)
{
((DbConnection) connection).EnlistTransaction(Transaction.Current);
}
return connection;
}
}
/// <inheritdoc />
public TransactionScope BeginTransactionScope()
{
return new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted });
}
}
}
I have attached a project to reproduce the error.
Debugger.Issue.zip
[EDIT] Add C# syntax highlighting by @karelz
While testing the .net core 2.1 implementation of TransactionScope I ran into the following issue.
We have a library that configures settings for DB Connections and Transaction scope (Data.Core). Other libraries call this library to execute queries using dapper.
When I execute the code without the debugger, everything runs fine. When I set a breakpoint in the unit test AND also in the method where the DB connection is opened. I then get the exception below.
Any ideas?
This is the test method in Data.Core.Tests:
This is DataStore class:
I have attached a project to reproduce the error.
Debugger.Issue.zip
[EDIT] Add C# syntax highlighting by @karelz