Skip to main content

connect-from-dotnet

Connects a .NET application to Azure SQL Database with Microsoft.Data.SqlClient: which package references are required, the encryption defaults and what changed, connection pooling and the keys that split a pool, and managed identity or other Microsoft Entra ID modes. Use when a user says "connect .NET to Azure SQL", "Microsoft.Data.SqlClient", "SqlConnection", "passwordless access for my .NET app", "managed identity for my API", "Active Directory Default", "Max Pool Size", "Encrypt=Strict", or asks whether "Microsoft.Data.SqlClient.Extensions.Azure" is needed. Also use when an app authenticates with a password locally and must use an identity in Azure. Covers packages, connection string keywords, pooling and Entra ID for .NET only; the ORM path is ef-core-azure-sql, and encryption doctrine plus transient-fault retry belong to connect-to-azure-sql.

معلومات المصدر

المستودع
microsoft/microsoft-sql
آخر نشاط في المصدر
٢٥ سبتمبر ٢٠٢٦ في ١٩:٥٣
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٥
التفرعات
٣

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
connect-from-dotnet
description
Connects a .NET application to Azure SQL Database with Microsoft.Data.SqlClient: which package references are required, the encryption defaults and what changed, connection pooling and the keys that split a pool, and managed identity or other Microsoft Entra ID modes. Use when a user says "connect .NET to Azure SQL", "Microsoft.Data.SqlClient", "SqlConnection", "passwordless access for my .NET app", "managed identity for my API", "Active Directory Default", "Max Pool Size", "Encrypt=Strict", or asks whether "Microsoft.Data.SqlClient.Extensions.Azure" is needed. Also use when an app authenticates with a password locally and must use an identity in Azure. Covers packages, connection string keywords, pooling and Entra ID for .NET only; the ORM path is ef-core-azure-sql, and encryption doctrine plus transient-fault retry belong to connect-to-azure-sql.
# Connect from .NET The driver is `Microsoft.Data.SqlClient`, encryption is on by default, pooling is automatic, and since version 7.0 Microsoft Entra authentication needs a **second package reference** that nothing in the connection string hints at. Measured 2026-09-03 on `Microsoft.Data.SqlClient` 7.0.2, `Microsoft.Data.SqlClient.Extensions.Azure` 7.0.2 and .NET SDK 8.0.421, with the commands in **Check it worked**. Encryption doctrine, retry and pool sizing are the same in every language and live in `connect-to-azure-sql`. Entity Framework Core is `ef-core-azure-sql`. ## The packages ```bash dotnet add package Microsoft.Data.SqlClient ``` `System.Data.SqlClient` is the older provider and receives no new features. A `using System.Data.SqlClient;` in a new file is a mistake worth fixing first. ## Gotcha: Entra ID needs a second package from version 7.0 7.0 moved the Entra dependencies out of the core package. Read the restored graph, do not guess: ```bash dotnet list package --include-transitive | grep -E '> (Azure\.Identity|Azure\.Core|Microsoft\.Identity\.Client) ' ``` On the core package alone that prints nothing, so the driver registers no Entra provider, and you can see that without a server at all: ```csharp using Microsoft.Data.SqlClient; var provider = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryDefault); Console.WriteLine(provider is null ? "NONE" : provider.GetType().FullName); ``` `NONE` means every `Active Directory *` mode has nothing to resolve to. Against a server that offers Microsoft Entra authentication the login then raises `ArgumentException`: `Cannot find an authentication provider for 'ActiveDirectoryDefault'`, naming the package to install. The fix is that package reference and no code change: ```bash dotnet add package Microsoft.Data.SqlClient.Extensions.Azure ``` Re-run both commands. The graph now lists `Azure.Identity`, `Azure.Core` and `Microsoft.Identity.Client`, and the provider prints `Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider`. The extension registers itself. SQL authentication, and applications that supply their own token through `AccessToken` or `AccessTokenCallback`, keep the lighter graph. **The local container is not where that exception reproduces.** The provider is looked up during the login exchange, so the `ArgumentException` needs a server offering Microsoft Entra authentication. Against the Azure SQL Database container, which has no Entra configuration, `Authentication=Active Directory Default` fails earlier and differently, as `Msg 18456`, `Login failed for user ''`, naming neither a provider nor a package; that one is `diagnose-connection-errors`. Decide the package from the graph and the mode, never from whether a local connection happened to succeed. ## Encryption defaults, and the version that changed them `Encrypt` defaults to `True` from version 4.0 and defaulted to `False` in 3.x and earlier. `TrustServerCertificate` defaults to `False`, and under `Encrypt=Strict` it is ignored and treated as false. So encryption is on and the certificate is validated, and connecting forces a trust decision rather than deferring one. Code written against a 3.x default surfaces that as a connection error on upgrade rather than as an upgrade note. Reach for `connect-to-azure-sql` before changing either value; the answer is almost never `TrustServerCertificate=True`. ## Pooling is automatic, and the connection string is the key Never cache a `SqlConnection`. Open one, use it, dispose it. The pool underneath does the reuse. ```csharp await using var connection = new SqlConnection(connectionString); await connection.OpenAsync(cancellationToken); ``` Four things decide whether pooling actually helps, with every default below read out of `SqlConnectionStringBuilder` on 7.0.2: - **The pool key is the whole connection string.** Two strings differing in any way, including a per-tenant `Application Name` or a rearranged keyword, get two pools that both count against the same server limits. Build the string once. - **`Connect Timeout` defaults to 15 seconds**, and Microsoft's guidance for Azure SQL Database is 30. Set it deliberately. `Pooling` is `True`, `Max Pool Size` 100 and `Min Pool Size` 0. - **`Connect Retry Count`, 1, and `Connect Retry Interval`, 10, are idle-connection resiliency inside the driver.** It transparently reconnects a dropped idle connection; it does not replay a failed query. From version 5 the effective default is raised for Azure SQL Database endpoints and again for serverless ones, so read it from the documentation rather than from the builder. Application-level retry is separate, and is `connect-to-azure-sql`. Keep both. - **`AccessTokenCallback` is part of the pool key.** A new lambda per `SqlConnection` creates a new pool per connection. Reference one shared static callback. Sizing the pool, and why the limit that bites is workers rather than sessions, is `connect-to-azure-sql`. ## Microsoft Entra ID Set `Authentication` in the connection string. `Active Directory Managed Identity` for an Azure-hosted workload, which is the production mode; `Active Directory Default` for development machines and CI, where the credential varies; `Active Directory Service Principal` for a registered app, client id in `User Id` and secret in `Password`. `Active Directory Password` is deprecated and obsolete in 7.0. System-assigned managed identity needs nothing beyond the mode. User-assigned supplies the identity in `User Id`, and **which identifier** depends on the driver version: the **client id** from 3.0 onwards, the **object id** on 2.1. Everything current wants the client id, and the object id fails at token acquisition with an error pointing at the identity endpoint, not at the connection string. ```csharp var connectionString = "Server=tcp:<server>.database.windows.net,1433;" + "Database=<database>;" + "Authentication=Active Directory Managed Identity;" + "User Id=<managed-identity-client-id>;" + // omit this line for a system-assigned identity "Encrypt=Mandatory;Connect Timeout=30;"; ``` `Active Directory Default` walks a chain of credential providers on the first connection, failing ones first, so it costs latency a production workload has no reason to pay. Name the credential type directly outside development. The identity still needs a database principal before it can connect. Creating it is `entra-id-auth`; wiring the identity through the hosting resources and deployment is `deploy-app-to-azure`. ## Check it worked Four checks. The first three need no database, so run them before blaming the network. **One: the dependency graph matches the authentication mode.** From the project directory: ```bash dotnet list package --include-transitive | grep -cE '> (Azure\.Identity|Azure\.Core|Microsoft\.Identity\.Client) ' ``` Expect `3` on a project that uses any `Active Directory *` mode, and `0` on one that does not. Measured 2026-09-03 on 7.0.2 with the extension package: `Azure.Identity` 1.18.0, `Azure.Core` 1.51.1, `Microsoft.Identity.Client` 4.84.2. Without it, all three absent. **Two: the driver has a provider for the mode you set.** Run the `GetProvider` snippet above. Expect `Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider`; `NONE` means the extension package is missing. That answer is the same on a laptop as in production. **Three: nothing in the tree undoes the defaults.** Both expect no output: ```bash grep -rn 'System\.Data\.SqlClient' --include='*.cs' . grep -rniE 'TrustServerCertificate *= *true' --include='*.cs' --include='*.json' --include='*.config' . ``` **Four: the connection you opened is the one you meant.** Ask the engine, over the application's own connection rather than from a query tool signed in as somebody else: ```csharp await using var connection = new SqlConnection(connectionString); await connection.OpenAsync(); await using var cmd = new SqlCommand( "SELECT c.encrypt_option, SUSER_SNAME() AS login, USER_NAME() AS db_user, DB_NAME() AS db " + "FROM sys.dm_exec_connections AS c WHERE c.session_id = @@SPID;", connection); await using var r = await cmd.ExecuteReaderAsync(); if (await r.ReadAsync()) Console.WriteLine($"encrypt={r[0]} login={r[1]} user={r[2]} db={r[3]}"); ``` One row, and each column settles a different question. `encrypt_option` is `TRUE` on an encrypted connection, so anything else means an `Encrypt=False` survived somewhere in the string. `login` is the identity the server believes it is talking to: for managed identity the Entra principal, and if it is the SQL login you meant to stop using, an old connection string is still in play. `db` catches the connection that opened happily against the wrong database. **Zero rows means a permission problem, not an unencrypted connection.** `sys.dm_exec_connections` needs `VIEW DATABASE STATE` on the database, or membership in the `##MS_ServerStateReader##` server role, and a least-privileged application user has neither by default. There is no unprivileged substitute: `CONNECTIONPROPERTY` carries `net_transport`, `protocol_type` and `auth_scheme`, not `encrypt_option`, and returns NULL for any other property name. ## Do not - Do not assume a connection string alone enables Entra ID on 7.0 or later. It needs the extension package, and `GetProvider` says in one line whether it is there. - Do not start new work on `System.Data.SqlClient`. - Do not set `TrustServerCertificate=True` to clear a certificate error. Read `connect-to-azure-sql`. - Do not cache or share a `SqlConnection` across requests, and do not vary the connection string per request, per tenant or per call site without meaning a separate pool. Cache nothing; the pool is the cache. - Do not use `Active Directory Password`, and do not pass a managed identity object id to a 3.0 or later driver; it wants the client id. - Do not hard-code a password, token, server hostname or identity id. - Do not write retry loops here. Transient-fault handling is one policy for every language, in `connect-to-azure-sql`. ## References - Open `references/entra-modes-and-connection-keywords.md` when the mode you need is not one of the three above, or before setting a keyword this body does not list: every `Authentication` value with the driver version it arrived in, and the encryption and pooling defaults read off 7.0.2. - [Entra authentication with SqlClient](https://learn.microsoft.com/sql/connect/ado-net/sql/azure-active-directory-authentication): every mode, the version it arrived in, and the 7.0 migration steps. Read before choosing a mode or debugging a provider error. - [SqlConnection.ConnectionString](https://learn.microsoft.com/dotnet/api/microsoft.data.sqlclient.sqlconnection.connectionstring): every keyword with its default. Read it rather than recalling a default. - [SQL Server connection pooling](https://learn.microsoft.com/sql/connect/ado-net/sql-server-connection-pooling): how the pool key is formed. Read it when two code paths appear to fight over connections. - [sys.dm_exec_connections](https://learn.microsoft.com/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-connections-transact-sql): the columns check four reads and the permission it needs. Read it when that query returns no row. - `connect-to-azure-sql`: encryption doctrine, retry, pool sizing, and the first-connect error on a paused database. `ef-core-azure-sql`: the same database through an object-relational mapper, whose connection string still comes from here.
عرض على GitHub