SQL Server 2022, ODBC Driver 18 e Visual Studio 2022: cause dei crash e guida completa al fix per app C#/.NET

La migrazione a SQL Server 2022 e all’ODBC Driver 18 può far “rompere” un’app .NET che funzionava con SQL Server 2019. Qui trovi cause, diagnostica e soluzioni per evitare di installare Visual Studio sui server di produzione.

Indice

Relazione fra SQL Server 2022, ODBC Driver 18 e Visual Studio 2022

L’aggiornamento di una soluzione C#/.NET a SQL Server 2022 introduce tre cambiamenti chiave:

  • Driver: ODBC Driver 18 sostituisce i provider legacy, abilita la crittografia per impostazione predefinita e richiede TLS 1.2.
  • Provider .NET: molte app usano ancora System.Data.SqlClient o ODBC via System.Data.Odbc; per funzionalità moderne e compatibilità sicurezza, è consigliato Microsoft.Data.SqlClient.
  • Runtime: Visual Studio installa una costellazione di prerequisiti (VC++ Redist, .NET Desktop Runtime, librerie COM, DACFx) che su una VM “pulita” non ci sono.

Risultato tipico: l’app che in laboratorio funziona (perché è presente VS) crasha su una VM minimalista. Installando Visual Studio il problema scompare, ma non è una soluzione accettabile in produzione.

Sintomi tipici

  • Crash all’avvio senza messaggi, oppure System.DllNotFoundException / BadImageFormatException nel registro eventi.
  • Connessione che fallisce dopo il passaggio a ODBC 18 con errori su certificato, crittografia o protocolli TLS.
  • Richiami a DLL non più presenti (sqlncli*.dll di Native Client).

Analisi delle cause (in sintesi)

Possibile causaSpiegazione
Componenti di runtime mancantiL’installazione di Visual Studio porta con sé runtime MSVC, .NET Desktop Runtime, librerie COM, MSBuild‑Tools, DACFx, ecc. L’app può dipendere da uno o più di questi file che, in una VM dove è presente solo l’ODBC Driver 18, non vengono installati.
Uso involontario di provider deprecatiSQL Server Native Client (SQLNCLI/SQLNCLI11) è stato rimosso da SQL Server 2022; se il programma tenta di caricarlo, all’assenza della DLL segue un crash.
Impostazioni di connessione non aggiornateODBC Driver 18 abilita TLS 1.2 e la crittografia per default; se il server non è configurato in modo coerente oppure Encrypt non è gestito correttamente, l’inizializzazione della connessione può fallire.

Perché installare Visual Studio “risolve” (ma non è la cura)

VS 2022 include i redistributable VC++ (2015‑2022), i runtime .NET Desktop nelle versioni correnti, componenti COM condivisi da tool Microsoft e spesso anche DACFx/SqlPackage. Se l’app fa P/Invoke verso librerie native o si appoggia a componenti COM registrati, l’assenza di questi prerequisiti su una macchina pulita porta a crash. La soluzione corretta è distribuire solo i runtime necessari nel tuo setup.

ODBC Driver 18: cosa cambia davvero

  • Crittografia by default: Encrypt è attivo di default. Se il server non ha un certificato valido o il nome non corrisponde al CN/SAN, la connessione fallisce.
  • TrustServerCertificate: per impostazione predefinita è disattivato; bypassare la validazione del certificato richiede esplicitare TrustServerCertificate=Yes (sconsigliato in produzione).
  • TLS: richiede TLS 1.2 (o superiore) sia lato client che server; suite obsolete non sono accettate.
  • Compatibilità: ODBC 18 è retro‑compatibile con SQL Server 2008+; non servono più driver multipli per versioni diverse.

Native Client è storia

SQL Server Native Client (SQLNCLI/SQLNCLI11) è deprecato e non è distribuito con SQL Server 2022. Se la tua app usa stringhe del tipo Provider=SQLNCLI11.1; o fa riferimento a sqlncli11.dll, devi migrare a:

  • ODBC Driver 18 con System.Data.Odbc;
  • oppure Microsoft.Data.SqlClient (ADO.NET moderno);
  • oppure Microsoft OLE DB Driver 19 for SQL Server se l’applicazione è OLE DB e non può essere modificata.

Soluzioni pratiche (passo‑passo)

Elimina dipendenze da Native Client

  • Aggiorna la stringa di connessione a Driver={ODBC Driver 18 for SQL Server}; oppure passa al provider ADO.NET Microsoft.Data.SqlClient (≥ v5.x consigliata).
  • Rimuovi dal setup qualsiasi MSI/merge‑module che installi sqlncli*.dll.

Distribuisci i runtime senza installare Visual Studio

Includi nel tuo installer:

  • Microsoft Visual C++ Redistributable 14.3x (x86 e/o x64, coerenti con l’architettura dell’app).
  • .NET Desktop Runtime corrispondente al target (es. 6.0 LTS o 8.0).
  • ODBC Driver 18 (x86 e/o x64, in base alla bitness dell’app).
  • DACFx/SqlPackage solo se effettivamente utilizzati a runtime (migrazioni schema, deploy dacpac).

Strumenti utili per creare un unico bootstrapper: WiX Burn, Inno Setup o MSIX Packaging.

Diagnosi rapida su VM pulita

  • Verifica i runtime .NET presenti: dotnet --list-runtimes
  • Controlla le DLL mancanti a ridosso del crash con strumenti come Dependency Walker o ProcMon (filtro su Result=NAME NOT FOUND).
  • Registro eventi → Applicazione: cerca eccezioni System.DllNotFoundException, BadImageFormatException (tipico mismatch x86/x64), errori di crittografia o TLS.

Convalida e modernizza la stringa di connessione

Allinea la configurazione del server e della stringa di connessione agli obblighi di ODBC 18:

  • Ambiente di produzione (consigliato): installa un certificato TLS valido su SQL Server, usa Encrypt=True e TrustServerCertificate=False.
  • Ambiente di test/lab: se il certificato non è disponibile, imposta Encrypt=Optional oppure TrustServerCertificate=Yes temporaneamente.

Esempi concreti

ADO.NET moderno (Microsoft.Data.SqlClient)

using Microsoft.Data.SqlClient;

var cs = new SqlConnectionStringBuilder
{
DataSource = "tcp:sqlserver.miodominio.local,1433",
InitialCatalog = "AppDb",
UserID = "app_user",
Password = "",
Encrypt = true,                // esplicito per evitare ambiguità di default
TrustServerCertificate = false // in produzione: valida il certificato
// IntegratedSecurity = true  // alternativa a UserID/Password
};

using var con = new SqlConnection(cs.ConnectionString);
await con.OpenAsync();
Console.WriteLine($"Connesso a {con.DataSource}, versione {con.ServerVersion}"); 

ODBC .NET con ODBC Driver 18

using System.Data.Odbc;

var cnString = "Driver={ODBC Driver 18 for SQL Server};" +
"Server=tcp:sqlserver.miodominio.local,1433;" +
"Database=AppDb;" +
"Uid=app_user;Pwd=;" +
"Encrypt=Optional;"; // per test; in prod preferire Encrypt=Yes/TrustServerCertificate=No

using var cn = new OdbcConnection(cnString);
cn.Open();
Console.WriteLine("OK via ODBC: " + cn.ServerVersion); 

Stringhe “pronte all’uso”

ScenarioStringa di connessione
ODBC 18 con SQL Auth (produzione)Driver={ODBC Driver 18 for SQL Server};Server=tcp:sqlserver.miodominio.local,1433;Database=AppDb;Uid=app_user;Pwd=*;Encrypt=Yes;TrustServerCertificate=No;
ODBC 18 con Integrated SecurityDriver={ODBC Driver 18 for SQL Server};Server=sqlserver.miodominio.local;Database=AppDb;Trusted_Connection=Yes;Encrypt=Yes;TrustServerCertificate=No;
ADO.NET (Microsoft.Data.SqlClient) con SQL AuthServer=tcp:sqlserver.miodominio.local,1433;Database=AppDb;User ID=app_user;Password=*;Encrypt=True;TrustServerCertificate=False;MultipleActiveResultSets=True;
Lab senza certificato...;Encrypt=Optional;TrustServerCertificate=Yes; (solo temporaneo)

Bitness, DSN e strumenti di amministrazione ODBC

  • Un’app x64 deve usare driver x64 e, se si appoggia a DSN, un DSN creato con C:\Windows\System32\odbcad32.exe.
  • Un’app x86 deve usare driver x86 e DSN creati con C:\Windows\SysWOW64\odbcad32.exe.
  • BadImageFormatException all’apertura della connessione è spesso un mismatch 32/64 bit tra app e driver.
  • Il tracing ODBC (tab “Tracing” dell’amministratore ODBC) può aiutare a individuare errori di handshake TLS/parametri.

Distribuzione automatizzata dei prerequisiti

Sequenza consigliata

  1. Visual C++ Redistributable (x64 → x86, se servono entrambi).
  2. .NET Desktop Runtime (versione target LTS o corrente).
  3. ODBC Driver 18 (x64/x86 in base alla tua app).
  4. Eventuali componenti facoltativi (DACFx/SqlPackage).
  5. La tua applicazione.

Comandi silent install (template)

:: VC++ Redist (x64)
vc_redist.x64.exe /install /quiet /norestart

:: VC++ Redist (x86)
vc_redist.x86.exe /install /quiet /norestart

:: .NET Desktop Runtime (8.0 x64)
windowsdesktop-runtime-8.0.x-win-x64.exe /quiet /norestart

:: ODBC Driver 18 (x64)
msiexec /i msodbcsql18.msi IACCEPTMSODBCSQLLICENSETERMS=YES /qn

:: ODBC Driver 18 (x86)
msiexec /i msodbcsql18_x86.msi IACCEPTMSODBCSQLLICENSETERMS=YES /qn 

Esempio WiX Burn: bundle minimale

<Bundle Name="App Setup" Version="1.0.0.0" Manufacturer="Contoso" UpgradeCode="{GUID}">
  <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
  <Chain>
    <PackageGroupRef Id="VcRedistX64" />
    <ExePackage Id="DotNetDesktopRuntime"
                SourceFile="windowsdesktop-runtime-8.0.x-win-x64.exe"
                InstallCommand="/quiet /norestart"
                Permanent="yes" Vital="yes" />
    <MsiPackage Id="Odbc18x64"
                SourceFile="msodbcsql18.msi"
                DisplayInternalUI="no"
                Permanent="yes" Vital="yes">
      <MsiProperty Name="IACCEPTMSODBCSQLLICENSETERMS" Value="YES"/>
    </MsiPackage>
    <MsiPackage Id="MyApp" SourceFile="MyApp.msi" />
  </Chain>
</Bundle>

Esempio Inno Setup: prerequisiti + app

[Run]
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/install /quiet /norestart"; Check: IsWin64
Filename: "{tmp}\windowsdesktop-runtime-8.0.x-win-x64.exe"; Parameters: "/quiet /norestart"; Check: IsWin64
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\msodbcsql18.msi"" IACCEPTMSODBCSQLLICENSETERMS=YES /qn"; StatusMsg: "Installazione ODBC Driver 18..."
Filename: "{app}\MyApp.exe"; Description: "Avvia l'applicazione"; Flags: postinstall nowait

Checklist di preflight

VoceCome verificare
VC++ Redist (x86/x64)Appwiz.cpl → “Microsoft Visual C++ 2015‑2022 Redistributable”; oppure controllo registro.
.NET Desktop Runtimedotnet --list-runtimes → presenza di Microsoft.WindowsDesktop.App nella versione attesa.
ODBC Driver 18Amministratore ODBC → “ODBC Driver 18 for SQL Server” nella scheda Driver.
Certificato serverCN/SAN corrisponde al nome usato nel parametro Server; catena di fiducia valida; non scaduto.
Bitness coerenteProcesso x86 usa driver x86; processo x64 usa driver x64; DSN creato nel giusto amministratore ODBC.

Diagnostica avanzata

Abilitare minidump con Windows Error Reporting

reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 2 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpCount /t REG_DWORD /d 10 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpFolder /t REGEXPANDSZ /d "C:\Dumps" /f

Riproduci il crash e analizza lo stack per identificare la libreria mancante o l’errore di handshake TLS.

Log utili nel Registro Eventi

  • Applicazione: eccezioni .NET (Source: .NET Runtime, Application Error).
  • System: errori di driver/certificati.
  • Microsoft‑Windows‑ODBC Driver Logs (se attivati): dettaglio sulle negoziazioni.

Migrazione verso Microsoft.Data.SqlClient

Se puoi toccare il codice, preferisci il provider ADO.NET Microsoft.Data.SqlClient rispetto a System.Data.SqlClient. Vantaggi:

  • Allineamento alle policy di sicurezza recenti (Encrypt di default nelle versioni moderne del provider).
  • Supporto migliorato a funzionalità come Always Encrypted, Azure Active Directory, MARS.
  • Rilascio indipendente dal framework, quindi aggiornabile senza cambiare il target .NET.

Consiglio operativo: imposta sempre esplicitamente Encrypt e TrustServerCertificate nella connection string per evitare sorprese con cambi di default tra versioni.

FAQ per decisioni rapide

DomandaRisposta
Serve Visual Studio 2022 per usare SQL Server 2022 + ODBC 18?No. VS non è richiesto; servono solo i runtime che VS installa automaticamente.
Devo usare SQL Server Native Client?No. Native Client è deprecato e non distribuito con SQL Server 2022; sostituiscilo con ODBC Driver 18 o, per OLE DB, con Microsoft OLE DB Driver 19.
È opzionale o obbligatorio installare Native Client insieme a SQL Server 2019/2022?Oggi è opzionale e sconsigliato; usa i driver moderni (ODBC 18 o Microsoft.Data.SqlClient).

Suggerimenti extra e buone pratiche

  • Compila l’app nella stessa architettura dei driver ODBC installati (x86/x64) ed evita AnyCPU se fai P/Invoke verso DLL native.
  • Se il crash persiste, strumenta l’avvio: logga le variabili d’ambiente, il PATH, le versioni di runtime e le eccezioni non gestite.
  • Abilita un test di integrazione che avvia l’eseguibile in una VM “pulita” con soli prerequisiti: intercetta regressioni prima del rilascio.
  • Documenta i prerequisiti in un file README‑Ops interno con i pacchetti da installare e le opzioni silent.
  • Se usi DSN, versione e denominazione dei driver devono essere coerenti con la VM target; valuta DSN‑less per evitare sorprese.

Script rapidi per verifiche di ambiente

PowerShell: verifica ODBC 18 e VC++

# ODBC Driver 18 installato?
Get-ItemProperty 'HKLM:\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers' |
  Select-Object -ExpandProperty 'ODBC Driver 18 for SQL Server' -ErrorAction SilentlyContinue

VC++ Redist 2015-2022

Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes','HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes' -ErrorAction SilentlyContinue |
ForEach-Object {
$v = (Get-ItemProperty $*.PsPath -ErrorAction SilentlyContinue)
[PSCustomObject]@{Arch=$*.PSChildName; Version="$($v.Major).$($v.Minor).$($v.Bld).$($v.Qfe)"; Installed=$v.Installed}
}

.NET Desktop Runtime

dotnet --list-runtimes | Select-String "Microsoft.WindowsDesktop.App" 

PowerShell: health‑check di connessione

$cs = "Driver={ODBC Driver 18 for SQL Server};Server=tcp:sqlserver.miodominio.local,1433;Database=AppDb;Uid=app_user;Pwd=*;Encrypt=Yes;TrustServerCertificate=No;"
Add-Type -AssemblyName System.Data
$con = New-Object System.Data.Odbc.OdbcConnection($cs)
try { $con.Open(); "Connesso: $($con.ServerVersion)" } catch { $_.Exception | Format-List -Force } finally { $con.Dispose() }

Piano di deploy consigliato

  1. Prepara un bundle che installa VC++ Redist, .NET Desktop Runtime, ODBC 18 e l’app.
  2. Configura SQL Server con certificato TLS valido (CN/SAN corrispondente al nome usato dai client).
  3. Imposta connection string esplicite con Encrypt/TrustServerCertificate coerenti con l’ambiente.
  4. Automaticamente testa su VM “pulita” in pipeline CI: esegui l’app, apri una connessione, verifica query triviale (SELECT 1).
  5. Monitora all’avvio i log applicativi ed eventi di sistema per individuare tempestivamente errori TLS o DLL.

Conclusione

Non serve Visual Studio per far girare un’app .NET con SQL Server 2022: servono i suoi runtime. Aggiornando i provider (ODBC 18 o Microsoft.Data.SqlClient), distribuendo i redistributable corretti e adeguando le impostazioni di sicurezza (Encrypt/TLS), puoi eliminare i crash all’avvio e standardizzare il deployment su VM pulite—senza installare strumenti di sviluppo sui server.


Riepilogo operativo

  • Driver: usa ODBC Driver 18 o Microsoft.Data.SqlClient; non usare Native Client.
  • Runtime: includi VC++ Redist e .NET Desktop Runtime nel tuo installer.
  • Sicurezza: configura certificato TLS su SQL Server oppure esplicita Encrypt=Optional solo in test.
  • Bitness: allinea x86/x64 tra app, driver e DSN.
  • Automazione: crea un bootstrapper e un test di integrazione su VM “pulita”.

Con queste azioni, la relazione fra SQL Server 2022, ODBC Driver 18 e Visual Studio 2022 torna a essere un vantaggio (sicurezza e stabilità) anziché una fonte di regressioni.

Appendice: mapping veloce problemi → rimedi

ProblemaPossibile causaRimedio immediato
Crash all’avvio senza logDLL native mancanti (VC++), COM non registratoInstalla VC++ Redist x64/x86; abilita WER dumps; verifica con ProcMon
Errore certificato/handshakeEncrypt attivo, certificato non valido o nome server non corrispondenteInstalla certificato valido; usa Encrypt=Yes, TrustServerCertificate=No
BadImageFormatExceptionMismatch x86/x64 tra app e driverAllinea bitness; reinstalla driver corretti; ricrea DSN nel giusto odbcad32.exe
DllNotFoundException: sqlncli11.dllUso di provider deprecatoMigra a ODBC 18 o Microsoft.Data.SqlClient; rimuovi riferimenti a Native Client
Funziona solo con VS installatoDipendenze implicite da runtime VSBundla i redistributable; verifica su VM pulita prima del rilascio
Indice