-
Notifications
You must be signed in to change notification settings - Fork 340
Migration Runtime and Compatibility
Compare results, not just successful connections. Data-shape and precision changes can be more consequential than an obvious exception.
| Area | What to exercise |
|---|---|
Nullable rowversion / timestamp results |
MDS uses DBNull rather than the legacy empty-byte-array shape. Check nulls before casting. Include outer-join results. |
| Decimal precision and scale | MDS's scale adjustment rounds by default. Verify stored values at scale boundaries, especially financial calculations. |
| Date and time parameters | Use TimeSpan, not DateTime, for DbType.Time. Sending a DateTime as DbType.Date truncates its time component. Verify round trips. |
| Exceptions | Retype SDS-specific handlers; check authentication and Always Encrypted error paths against the selected release. |
| Asynchronous operations | Exercise synchronous and asynchronous open/read/execute, cancellation, disposal, and large payloads. Remove assumptions about synchronous completion. |
| Observability | Set a stable application name if dashboards or server-side classification depend on it. Recheck diagnostic subscriptions and identifiers. |
| Connection-string sharing | MDS builders can emit keyword spellings an SDS parser does not accept. Use provider-appropriate configuration at each boundary. |
| Always Encrypted | Exercise custom key-provider registration, precedence, permissions, and enclave paths your application uses. |
MDS accepts both the original keywords and newer aliases with spaces. Its connection-string builder can emit the spaced aliases, which SDS does not accept:
| MDS builder output | Spelling accepted by SDS and MDS |
|---|---|
Application Intent=ReadOnly |
ApplicationIntent=ReadOnly |
Multi Subnet Failover=True |
MultiSubnetFailover=True |
Prefer building each connection string with the provider that will consume it. If a shared configuration must support both providers, map these keyword names explicitly and check every other setting for compatibility. Do not remove spaces from the entire string: that can corrupt server names, database names, credentials, and other values. An MDS-only setting does not become SDS-compatible just by changing whitespace.
.NET Framework uses Windows National Language Support (NLS). Modern .NET uses International Components for Unicode (ICU) by default on supported Windows versions, as it does on Linux/macOS. This runtime change can affect culture-sensitive System.Data.SqlTypes.SqlString comparisons independently of the provider migration.
Test client-side equality and ordering against the database's actual collation, including application-relevant casing, accents, and punctuation. Do not assume client comparisons will match SQL Server after the runtime move.
For a Windows application that requires the previous NLS behavior, merge this setting into the application's runtimeconfig.json before starting the process:
{
"runtimeOptions": {
"configProperties": {
"System.Globalization.UseNls": true
}
}
}Preserve existing runtime settings. NLS is Windows-only, and this is an application-wide .NET setting, not a SqlClient-only switch or a guarantee of equivalence to every SQL collation. Retest other culture-sensitive operations. See NLS configuration guidance for project/environment alternatives and precedence rules.
Prefer correcting application assumptions. Where a selected release supports a compatibility switch, record the exact name, purpose, owner, and removal condition.
Two established migration controls are Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior and Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal. Enabling them restores the corresponding legacy null/decimal behavior; it also changes semantics process-wide. Validate that this is what all affected callers require.
Configure switches before the driver first uses them, normally at startup before SqlClient initialization. Many values are cached. Do not copy a development-branch switch list into a released application: availability, defaults, and interactions depend on version.
Leave optional pool and networking performance experiments unchanged during the initial migration. Benchmark those independently afterward.
The statement "GetSchemaTable() never returns null in modern MDS" is not a valid migration rule. The 2.0.0 empty-table change was reverted in 2.0.1. Retain appropriate null handling; do not replace it with an unconditional schema.Rows dereference.
Next: Deployment and rollout.
Sources: porting guide, decimal behavior, schema-table reversion, 3.0 behavior changes, globalization guidance.
Home | ADO.NET driver docs | Release notes | Support lifecycle
Report security vulnerabilities privately to MSRC. Never share credentials or access tokens in public reports.