Skip to content

SqlClient doesn't work with Native AOT on windows #1941

@vonzshik

Description

@vonzshik

Given a small hello world example:

await using var conn = new SqlConnection(ConnectionString);
await conn.OpenAsync();
await using var cmd = new SqlCommand("SELECT 'Hello World'", conn);
await using var reader = await cmd.ExecuteReaderAsync();
if (!await reader.ReadAsync())
	throw new Exception("Got nothing from the database");

var value = reader.GetFieldValue<string>(0);
if (value != "Hello World")
	throw new Exception($"Got {value} instead of the expected 'Hello World'");

throws on windows with Native AOT:

Unhandled Exception: System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.
 ---> System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.
 ---> System.DllNotFoundException: Unable to load DLL 'Microsoft.Data.SqlClient.SNI.dll' or one of its dependencies: The specified module could not be found.
   at System.Runtime.InteropServices.NativeLibrary.LoadLibErrorTracker.Throw(String) + 0x79
   at Internal.Runtime.CompilerHelpers.InteropHelpers.FixupModuleCell(InteropHelpers.ModuleFixupCell*) + 0xdb
   at Internal.Runtime.CompilerHelpers.InteropHelpers.ResolvePInvokeSlow(InteropHelpers.MethodFixupCell*) + 0x2f
   at Microsoft.Data.SqlClient.SNINativeMethodWrapper.SNIInitialize(IntPtr) + 0x27
   at Microsoft.Data.SqlClient.SNILoadHandle..ctor() + 0x76
   at Microsoft.Data.SqlClient.SNILoadHandle..cctor() + 0x1c
   at System.Runtime.CompilerServices.ClassConstructorRunner.EnsureClassConstructorRun(StaticClassConstructionContext*) + 0xc6
   --- End of inner exception stack trace ---
   at System.Runtime.CompilerServices.ClassConstructorRunner.EnsureClassConstructorRun(StaticClassConstructionContext*) + 0x167
   at System.Runtime.CompilerServices.ClassConstructorRunner.CheckStaticClassConstructionReturnGCStaticBase(StaticClassConstructionContext*, Object) + 0xd
   at Microsoft.Data.SqlClient.TdsParserStateObjectFactory.get_EncryptionOptions() + 0x12
   at Microsoft.Data.SqlClient.TdsParser..cctor() + 0x1f
   at System.Runtime.CompilerServices.ClassConstructorRunner.EnsureClassConstructorRun(StaticClassConstructionContext*) + 0xc6
   --- End of inner exception stack trace ---
   at System.Runtime.CompilerServices.ClassConstructorRunner.EnsureClassConstructorRun(StaticClassConstructionContext*) + 0x167
   at System.Runtime.CompilerServices.ClassConstructorRunner.CheckStaticClassConstructionReturnNonGCStaticBase(StaticClassConstructionContext*, IntPtr) + 0xd
   at Microsoft.Data.SqlClient.TdsParser..ctor(Boolean, Boolean) + 0x11
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo, String, SecureString, Boolean, SqlConnectionString, SqlCredential, TimeoutTimer) + 0x16e
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer, SqlConnectionString, SqlCredential, String, SecureString, Boolean) + 0x1cb
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity, SqlConnectionString, SqlCredential, Object, String, SecureString, Boolean, SqlConnectionString, SessionData, Boolean, String, DbConnectionPool) + 0x386
   at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions, DbConnectionPoolKey, Object, DbConnectionPool, DbConnection, DbConnectionOptions) + 0x2f9
   at Microsoft.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool, DbConnection, DbConnectionOptions, DbConnectionPoolKey, DbConnectionOptions) + 0x40
   at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection, DbConnectionOptions, DbConnectionInternal) + 0x373
   at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection, DbConnectionOptions, DbConnectionInternal) + 0x5e
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection, UInt32, Boolean, Boolean, DbConnectionOptions, DbConnectionInternal&) + 0x4d1
   at Microsoft.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen() + 0x149
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xb6
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task) + 0x42
   at SqlClientAOT.Program.<Main>d__0.MoveNext() + 0x152
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20
   at SqlClientAOT.Program.<Main>d__0.MoveNext() + 0x8bd
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x20
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xb6
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task) + 0x42
   at SqlClientAOT.Program.<Main>(String[]) + 0x20
   at SqlClientAOT!<BaseAddress>+0xd0ecab

Works fine on linux (ubuntu wsl). Would have been nice if SqlClient supported Native AOT on windows.
Also, the resulting binary on linux is about 45mb, but that's a different issue altogether.

.NET 7.0.3, SqlClient 5.1.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions