Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SqlAuthenticationProviderManager.ctor throws an Exception when called from Unmanaged Code #500

Closed
Kylon92 opened this issue Mar 31, 2020 · 4 comments

Comments

@Kylon92
Copy link

Kylon92 commented Mar 31, 2020

Hello,

we tried migrating from System.Data.SQLClient to Microsoft.Data.SQLClient, and everything seems to work fine except when calling the Code from COM Interop,
the class SqlAuthenticationProviderManager tries to to call System.Configuration.ConfigurationManager.GetSection with "SqlAuthenticationProviders" as Parameter,
however, ConfigurationManager.GetSection will throw an Exception since it always uses System.Reflection.Assembly.GetEntryAssembly().Location, which is null when called from COM Interop.
While the code is in a try catch block, only ConfigurationErrorsException's are caught but the ClientConfigPath class throws a PlatformNotSupportedException if the EntryAssembly is null.

System.TypeInitializationException
HResult=0x80131534
Message=The type initializer for 'Microsoft.Data.SqlClient.SqlAuthenticationProviderManager' threw an exception.
Source=Microsoft.Data.SqlClient
StackTrace:
at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling, String accessToken, DbConnectionPool pool, SqlAuthenticationProviderManager sqlAuthProviderManager)
at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
at Microsoft.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions)
at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry) at Microsoft.Data.SqlClient.SqlConnection.Open() at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(Boolean errorsExpected) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.InitializeReader(DbContext _, Boolean result)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func3 operation, Func3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.MoveNext() at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1 source)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
at Nippon.Persistance.Controller.MFPController.GetMFP(String mfp) in E:\Nippon.NET\7. Persistance Layer\Nippon.Persistance\Controller\MFPController.cs:line 29
at Nippon.Common.Interop.Base.VB6InteropWindow..ctor() in E:\Nippon.NET\2. Presentation Layer\WPF\Nippon.Common.Interop\Base\VB6InteropWindow.cs:line 34
at Nippon.Controls.Views.Bestand..ctor() in E:\Nippon.NET\2. Presentation Layer\WPF\Nippon.Common.Interop\Views\Bestand\Bestand.xaml.cs:line 38

This exception was originally thrown at this call stack:
System.Configuration.ClientConfigPaths.ClientConfigPaths(string, bool)
System.Configuration.ClientConfigPaths.GetPaths(string, bool)
System.Configuration.ClientConfigurationHost.ConfigPaths.get()
System.Configuration.ClientConfigurationHost.GetStreamName(string)
System.Configuration.ClientConfigurationHost.IsAppConfigHttp.get()
System.Configuration.Internal.DelegatingConfigHost.IsAppConfigHttp.get()
System.Configuration.ClientConfigurationSystem.ClientConfigurationSystem()
System.Configuration.ConfigurationManager.EnsureConfigurationSystem()

Inner Exception 1:
InvalidOperationException: Failed to read the config section for authentication providers.

Inner Exception 2:
ConfigurationErrorsException: Configuration system failed to initialize

Inner Exception 3:
PlatformNotSupportedException: Operation is not supported on this platform.

To reproduce

Make sure System.Reflection.Assembly.GetEntryAssembly() is null by calling from any non .NET Code, open any Microsoft.Data.SqlClient.SqlConnection with .Open() causes an InvalidOperationException

Expected behavior

The behavior can stay the same however there should be some sort of new SqlServerDbContextOptionsBuilder option to use an AlternateConfigurationExe when calling from unmanaged Code

Further technical details

Microsoft.Data.SqlClient version: 1.1.1
.NET target: Core 3.1
SQL Server version: SQL Server 2019

@cheenamalhotra
Copy link
Member

Hi @Kylon92

Could you please provide us a repro app to reproduce the problem?

@Kylon92
Copy link
Author

Kylon92 commented Apr 1, 2020

Hi,

i made a Testproject to demonstrate the Issue, you can find it at https://github.com/Kylon92/issue500test
While making it i noticed that C# COM Consumer to C# Com Server does not trigger the issue as System.Reflection.Assembly.GetEntryAssembly() is filled.
However when you test it with VBA from Excel (ComConsumerVBA.xlsm) or with VB6 is will crash as soon as you try to open a Microsoft.Data.SQLClient.SQLConnection.
I have included a VBA Testcase and i recommend using it as the VB6 Testproject requires to run a setup(VB6 Consumer/dist/setup.exe) to install missing vb6 runtime DLLs

@cheenamalhotra
Copy link
Member

I believe PR #573 will also fix this issue, @Kylon92 could you give it a try and let us know?

@Kylon92
Copy link
Author

Kylon92 commented May 26, 2020

@cheenamalhotra I tried it and now it works, thank you.

@Kylon92 Kylon92 closed this as completed May 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants