dotnet / SqlClient

Microsoft.Data.SqlClient provides database connectivity to SQL Server for .NET applications.
MIT License
839 stars 280 forks source link

TransactionScope in 2.1 throwing exception only during debugging in VS2017 15.7.0 Preview 6.0 #21

Closed BrotherOdin closed 2 years ago

BrotherOdin commented 6 years ago

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

BrotherOdin commented 6 years ago

dotnet --info

.NET Core SDK (reflecting any global.json):
 Version:   2.1.300-rc1-008673
 Commit:    f5e3ddbe73

Runtime Environment:
 OS Name:     Windows
 OS Version:  6.3.9600
 OS Platform: Windows
 RID:         win81-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.300-rc1-008673\

Host (useful for support):
  Version: 2.1.0-rc1
  Commit:  eb9bc92051

.NET Core SDKs installed:
  1.0.0 [C:\Program Files\dotnet\sdk]
  1.0.4 [C:\Program Files\dotnet\sdk]
  1.1.0-preview1-005098 [C:\Program Files\dotnet\sdk]
  1.1.0 [C:\Program Files\dotnet\sdk]
  1.1.8 [C:\Program Files\dotnet\sdk]
  2.0.3 [C:\Program Files\dotnet\sdk]
  2.1.4 [C:\Program Files\dotnet\sdk]
  2.1.104 [C:\Program Files\dotnet\sdk]
  2.1.200-preview-007597 [C:\Program Files\dotnet\sdk]
  2.1.300-rc1-008673 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0-rc1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download
karelz commented 6 years ago

Distributed transactions are not supported yet - see #16755

BrotherOdin commented 6 years ago

That is part of the bug. This code should never try to elevate to use Distributed transactions. It seems to do it only if you add the breakpoints and stop during debugging.

If you just execute, there is no Distributed transaction and it works just fine.

jimcarley commented 6 years ago

This looks to be an issue with System.Data, based on this part of the callstack:

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, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry) at System.Data.SqlClient.SqlConnection.Open()

System.Data is asking for the "ExportCookie" for the transaction. That can only be obtained after promoting the transaction.

System.Data should be trying to do a Transaction.EnlistPromotableSinglePhase first, before asking for the Export Cookie. But if EnlistPromotableSinglePhase returns "false", that means that a call to EnlistDurable or another EnlistPromotableSinglePhase has already been made for the transaction. This could lead to System.Data trying to get the Export Cookie.

Adding label for area-System.Data.SqlClient and adding @saurabh500

karelz commented 6 years ago

cc @David-Engel @keeratsingh

BrotherOdin commented 6 years ago

Is this something that will be fixed as part of the 2.1 release?

keeratsingh commented 6 years ago

Hi @BrotherOdin I am unable to repro the issue using the repro code you provided in my enviornment, I have stripped down the repro you provided to a bare minimum where it uses .NET SDK Runtime Version 2.1.300-rc1-008673 and SqlClient Version 4.5.0-rc1. I have tried both running it via command prompt and placing debug breakpoints using Visual Studio, however I still cannot repro the issue. I have attached the Visual Studio solution of the minimal repro, could you kindly try the same and let me know if you see the exception in your environment ? adhoc_gh_29633.zip

PS D:\adhoc_gh_29633> dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   2.1.300-rc1-008673
 Commit:    f5e3ddbe73

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17134
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.300-rc1-008673\

Host (useful for support):
  Version: 2.1.0-rc1
  Commit:  eb9bc92051

.NET Core SDKs installed:
  2.1.300-preview2-008533 [C:\Program Files\dotnet\sdk]
  2.1.300-rc1-008673 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0-preview2-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0-preview2-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.0-preview2-26406-04 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0-rc1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download
PS D:\adhoc_gh_29633>
PS D:\adhoc_gh_29633> cat .\adhoc.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <RuntimeFrameworkVersion>2.1.0-rc1</RuntimeFrameworkVersion>

  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Data.SqlClient" Version="4.5.0-rc1" />
   </ItemGroup>
</Project>
PS D:\adhoc_gh_29633>
BrotherOdin commented 6 years ago

I will try it and report back. Stay tuned.

BrotherOdin commented 6 years ago

The one in the ZIP is using System.Data.SqlClient (4.6.0-preview1-26529-04) rather than 4.5.0-rc1 so I could not try it.

Once I update it back to 4.5.0-rc1, I am able to recreate the problem.

This are the steps I followed. Updated adhoc.csproj to use 4.5.0-rc1. (Basically the same as you referenced above) Open Visual Studio Enterprise 2017 Preview Version 15.8.0 Preview 6.0 Open Solution Compile Set the two breakpoints as indicated in the code F5 to Run - Hits first breakpoint F10 - To step through until it hits this line: connection.Open(); Exception thrown.

We can do an interactive session if you would like. Just let me know.

keeratsingh commented 6 years ago

@BrotherOdin Thank you for the confirmation and detailed steps to repro the issue. I see we differ in OS environments, your logs suggest you are using win81-x64 while I am trying to repro the issue in win10-x64. I will try to setup and repro the issue in win81-x64 environment and get back to you.

StevenRasmussen commented 6 years ago

I think I'm running into a similar issue... although it's kind of intermittent. Sometimes I'll get the error and sometimes I don't. And it doesn't just happen when a breakpoint is set. I know this doesn't really help with troubleshooting but I wanted to let you know that I'm experiencing it too.

keeratsingh commented 6 years ago

@SimplerSoftware Thank you for sharing the information. Could you kindly share your dotnet --info output as well.

StevenRasmussen commented 6 years ago

@keeratsingh - here you go:

.NET Core SDK (reflecting any global.json):
 Version:   2.1.300
 Commit:    adab45bf0c

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17134
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.300\

Host (useful for support):
  Version: 2.1.0
  Commit:  caa7b7e2ba

.NET Core SDKs installed:
  1.1.0 [C:\Program Files\dotnet\sdk]
  2.0.0 [C:\Program Files\dotnet\sdk]
  2.0.2 [C:\Program Files\dotnet\sdk]
  2.0.3 [C:\Program Files\dotnet\sdk]
  2.1.1-preview-007094 [C:\Program Files\dotnet\sdk]
  2.1.2 [C:\Program Files\dotnet\sdk]
  2.1.4 [C:\Program Files\dotnet\sdk]
  2.1.100 [C:\Program Files\dotnet\sdk]
  2.1.101 [C:\Program Files\dotnet\sdk]
  2.1.103 [C:\Program Files\dotnet\sdk]
  2.1.104 [C:\Program Files\dotnet\sdk]
  2.1.200-preview-007474 [C:\Program Files\dotnet\sdk]
  2.1.200-preview-007589 [C:\Program Files\dotnet\sdk]
  2.1.200 [C:\Program Files\dotnet\sdk]
  2.1.201 [C:\Program Files\dotnet\sdk]
  2.1.300-preview1-008174 [C:\Program Files\dotnet\sdk]
  2.1.300-rc1-008673 [C:\Program Files\dotnet\sdk]
  2.1.300 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0-preview1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0-preview1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0-preview1-26216-03 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0-rc1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

Edit: Formatted response by @keeratsingh

keeratsingh commented 6 years ago

I have setup a Windows 8.1 environment and was able to repro the issue only once against a local 2017 SQLServer, that too on a clean VM, fortunately I was able to capture the dump and trace with the line numbers to have a better picture of the path. I haven't been able to repro this on Windows 10. On further investigation while debugging through code I found that System.Data.SqlClient is indeed calling Transaction.EnlistPromotableSinglePhase before it calls GetTransactionCookie.

Now the above is just a theory, so far which I have not been able to confirm if EnlistNonNull is indeed being called twice, since the issue is not reproable consistently.

@BrotherOdin Is the issue reproing consistently for you ? Also, to confirm which version of SQLServer are you seeing this issue with, is it local or remote SQLServer ?

   at System.Transactions.Distributed.DistributedTransactionManager.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken) in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\DistributedTransaction.cs:line 45
   at System.Transactions.TransactionInterop.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken) in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\TransactionInterop.cs:line 310
   at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx) in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\TransactionState.cs:line 4542
   at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx) in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\TransactionState.cs:line 3333
   at System.Transactions.EnlistableStates.Promote(InternalTransaction tx) in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\TransactionState.cs:line 682
   at System.Transactions.Transaction.Promote() in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\Transaction.cs:line 1131
   at System.Transactions.TransactionInterop.ConvertToDistributedTransaction(Transaction transaction) in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\TransactionInterop.cs:line 42
   at System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts) in E:\A\_work\165\s\corefx\src\System.Transactions.Local\src\System\Transactions\TransactionInterop.cs:line 86
   at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts) in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlInternalConnection.cs:line 593
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlInternalConnection.cs:line 458
   at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction) in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionPool.cs:line 1228
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionPool.cs:line 1216
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionPool.cs:line 1043
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\ProviderBase\DbConnectionFactory.cs:line 151
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) in E:\A\_work\4\s\corefx\src\Common\src\System\Data\ProviderBase\DbConnectionInternal.cs:line 325
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlConnection.cs:line 1153
   at System.Data.SqlClient.SqlConnection.Open() in E:\A\_work\4\s\corefx\src\System.Data.SqlClient\src\System\Data\SqlClient\SqlConnection.cs:line 689
   at adhoc.DataStore.get_Connection() in C:\Users\win81user\Downloads\adhoc_gh_29633\adhoc\DataStore.cs:line 38
   at adhoc.gh_29633_TransactionScopeExecption.Main(String[] args) in C:\Users\win81user\Downloads\adhoc_gh_29633\adhoc\gh_29633_TransactionScopeExecption.cs:line 20
BrotherOdin commented 6 years ago

I am getting this on a local SQL Server Running .

Microsoft SQL Server 2016 (SP1-CU2) (KB4013106) - 13.0.4422.0 (X64) Mar 6 2017 14:18:16 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows 8.1 Enterprise 6.3 (Build 9600: )

I get this problem every time.

ciragithub commented 6 years ago

On my environment, I am able to reproduce this behavior every time. VS 2017 15.7.3 (same with SQL Server Developer editions 2014/2016) Windows 10 Enterprise 64 bit

C:\Windows\system32>dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   2.1.300
 Commit:    adab45bf0c

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17134
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.300\

Host (useful for support):
  Version: 2.1.0
  Commit:  caa7b7e2ba

.NET Core SDKs installed:
  2.1.201 [C:\Program Files\dotnet\sdk]
  2.1.300 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

Links to pictures: https://1drv.ms/f/s!AjFU1uWlNw1R23_BMF6EWfJs6tgl OkTest.png - test run without debug DebugFailTest.png - test run in debug

I found this issue when I was searching for the same exception/issue that we encounter in our solution. Our use case is that we have 2 separate DbContexts and whenever we create TransactionScope and use second DbContext, the above "Platform not supported" exception is thrown - that is, with 2 DBContexts with the same connection strings and both wrapped in 1 TransactionScope, somehow it always gets promoted to distributed transactions.

jimcarley commented 6 years ago

@ciragithub And you are only seeing this problem when debugging, right? You don't see the PlatformNotSupported exception when using the second DbContext object within a TransactionScope when NOT running in the debugger?

BrotherOdin commented 6 years ago

Correct. Just calling code normally it works as expected.

On Fri, Jun 8, 2018 at 8:55 PM Jim Carley notifications@github.com wrote:

@ciragithub https://github.com/ciragithub And you are only seeing this problem when debugging, right? You don't see the PlatformNotSupported exception when using the second DbContext object within a TransactionScope when NOT running in the debugger?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dotnet/corefx/issues/29633#issuecomment-395921364, or mute the thread https://github.com/notifications/unsubscribe-auth/ACLifj6BY9It8xnulybO1MDREp634FGlks5t6w7ngaJpZM4T5zTP .

ciragithub commented 6 years ago

@jimcarley

  1. As for @BrotherOdin use case, it happens on my environment every time (reproduced every time) exactly as described above (only happens when test is run in DEBUG mode, test run without DEBUG mode passes).
  2. As for two DBContexts in one TransactionScope, PlatformNotSupported exception is thrown
    in both cases (DEBUG & without DEBUG).
  3. More detailed explanation: Our usage scenario involves injecting with AutoFac services->repositories->DbContexts which are called from Web.API controllers in async/await fashion. If you think it would be helpful, I can create small repro solution and upload it here (please let me know, thanks in advance).
ciragithub commented 6 years ago

@jimcarley I uploaded Transactions.7z as a repro solution (the same link as above, https://1drv.ms/f/s!AjFU1uWlNw1R23_BMF6EWfJs6tgl ) Please just create local Transactions database and execute Update-database, with startup project Transactions.Persistence (of course, if needed, change accordingly connection string in appsettings.development.json)

NOTE: Solution is fairly common approach/pattern in some DDD implementation with EF Core & Autofac injected services->repositories->DbContexts.

You have 3 Web.API TestController actions (test1, test2, test3) and in test1 action you can always reproduce above "Platform not supported" exception.

keeratsingh commented 6 years ago

@ciragithub

Please just create local Transactions database and execute Update-database, with startup project Transactions.Persistence

Thank you for sharing the repro, could you kindly elaborate the repro steps further in detail, I am not sure I understand on how to set Transactions.Persistence as startup project as it has output type as Class Library and not an executable.

ciragithub commented 6 years ago

@keeratsingh Startup project should be Transactions.API (image launchSettings.png , the same link as above, https://1drv.ms/f/s!AjFU1uWlNw1R23_BMF6EWfJs6tgl ).

As for "Please just create local Transactions database and execute Update-database, with startup project Transactions.Persistence", that refers to Default project in PowerShell (Package Manager Console) console in VS2017 when you do Upgrade-Database (sorry for potential misunderstanding).

keeratsingh commented 6 years ago

@ciragithub

Documentation The code creates the TransactionScope block with a using statement and opens the first connection, which automatically enlists it in the TransactionScope. The transaction is initially enlisted as a lightweight transaction, not a full distributed transaction. The second connection is enlisted in the TransactionScope only if the command in the first connection does not throw an exception. When the second connection is opened, the transaction is automatically promoted to a full distributed transaction.

The code below in the file Controllers\TestController.cs is essentially opening a second connection within the same transaction scope when the method _codebookQueryService.GetCommisions() is called. This promotes the Transaction to a distributed transaction as explained in the documentation above. Therefore you see the exception in both cases Debug and Non-Debug and as per #16755 Distributed transactions are not supported yet, thus, this is the expected behavior in the repro you shared.

//THIS WILL ALWAYS THROW
using (var scope = TransactionScopeFactory.CreateScope(TransactionScopeAsyncFlowOption.Enabled))
{
    var result = await _userQueryService.FindById(3);
    var commision = await _codebookQueryService.GetCommisions();

    return Ok(result);
}
ciragithub commented 6 years ago

@keeratsingh

Firstly, I am really sorry for replying so late to your last answer... Yes, I concluded in the meantime also that our usage patterns of TransactionScope will not work with EF Core, since support for the ambient transactions in EF Core is not even planned (in the near future, at least - good summary, for other potential viewers... http://weblogs.thinktecture.com/pawel/2018/06/entity-framework-core-use-transactionscope-with-caution.html ) In my personal opinion, this is very unfortunate decision, since real world applications would benefit it strongly, but I understand the reasons/priorities behind it, at least at the moment. Thanks again for your answers regarding that.

As for the original issue raised in this thread (from @BrotherOdin ), it is still valid/existing issue:

C:\Windows\system32>dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   2.1.402
 Commit:    3599f217f4

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17134
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.402\

Host (useful for support):
  Version: 2.1.4
  Commit:  85255dde3e

.NET Core SDKs installed:
  2.1.201 [C:\Program Files\dotnet\sdk]
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.300 [C:\Program Files\dotnet\sdk]
  2.1.400 [C:\Program Files\dotnet\sdk]
  2.1.401 [C:\Program Files\dotnet\sdk]
  2.1.402 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.3-servicing-26724-03 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

C:\Windows\system32>

This time, however, after update of NuGet packages from the @BrotherOdin solution-zip, I get errors - (image DebugFailTest-2018-09-22.PNG , the same link as above, https://1drv.ms/f/s!AjFU1uWlNw1R23_BMF6EWfJs6tgl ).

Alchemy86 commented 5 years ago

I had issues along this line, exact same error at one point. Regardless, I ended up getting what I wanted to work so have a poor implementation shared here: https://github.com/Alchemy86/DapperTransactionRunnerExample might be of help might not.

zhangsquall commented 5 years ago

I have this issue in debugging mode on windows 10. But in production mode, it does not appear. Below is my dotnet --info

.NET Core SDK (reflecting any global.json): Version: 2.2.203 Commit: e5bab63eca

Runtime Environment: OS Name: Windows OS Version: 10.0.17763 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\2.2.203\

Host (useful for support): Version: 2.2.4 Commit: f95848e524

.NET Core SDKs installed: 2.1.503 [C:\Program Files\dotnet\sdk] 2.1.504 [C:\Program Files\dotnet\sdk] 2.1.600 [C:\Program Files\dotnet\sdk] 2.1.601 [C:\Program Files\dotnet\sdk] 2.1.602 [C:\Program Files\dotnet\sdk] 2.2.103 [C:\Program Files\dotnet\sdk] 2.2.104 [C:\Program Files\dotnet\sdk] 2.2.105 [C:\Program Files\dotnet\sdk] 2.2.202 [C:\Program Files\dotnet\sdk] 2.2.203 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed: Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

divega commented 5 years ago

As recently announced in the .NET Blog, focus on new SqlClient features an improvements is moving to the new Microsoft.Data.SqlClient package. For this reason, we are moving this issue to the new repo at https://github.com/dotnet/SqlClient. We will still use https://github.com/dotnet/corefx to track issues on other providers like System.Data.Odbc and System.Data.OleDB, and general ADO.NET and .NET data access issues.

coredevsushant commented 5 years ago

do we have any solution I am running in same issue with .net core 2.2

cheenamalhotra commented 3 years ago

Hi @BrotherOdin @sushantraje2000 @zhangsquall @Alchemy86 @ciragithub

I tested this issue today with provided repro application and I was able to reproduce issue with EF Core v2.1.0-rc1-final But I tried again with EF Core v3.1.9 (tested both netcoreapp2.1 and netcoreapp3.1) that references Microsoft.Data.SqlClient now and this issue seems to be resolved.

Could someone verify and confirm so we can close this issue?

Thanks!

cheenamalhotra commented 2 years ago

@David-Engel @DavoudEshtehari I wonder if this can be closed since there is no activity or reports of the same?

JRahnama commented 2 years ago

Closing due to inactivity. Feel free to comment if still experiencing the issue.