Quickstart: Gebruik Microsoft. Data.SqlClient in een ASP.NET Core-app

In deze quickstart bouw je een ASP.NET Core minimale API met Microsoft.Data.SqlClient 7.1.1.

Je begint met een lege map, de .NET SDK en een SQL Server- of Azure SQL-database die je vanaf je computer kunt bereiken. Je eindigt met een web-API die een bericht toevoegt aan een tabel en het terugleest via ID.

Daarbij doet de app het volgende:

  • Leest zijn verbindingsreeks uit de ASP.NET Core-configuratie. Voor lokale ontwikkeling komt de waarde van gebruikersgeheimen, dus het blijft buiten je projectmap.
  • Registreert een dataklasse met afhankelijkheidsinjectie.
  • Opent en sluit een verbinding voor elk verzoek, waardoor de standaardverbindingspool fysieke verbindingen kan hergebruiken.
  • Geeft de CancellationToken van het verzoek door aan elke databaseaanroep.

De app gebruikt dezelfde dbo.SqlClientQuickstart tabel als Quickstart: Verbind en vraag op met Microsoft.Data.SqlClient. Je kunt eerst een van beide quickstarts doen.

Prerequisites

De huidige ASP.NET Core draait op .NET, niet op het .NET Framework. Om de driver van .NET Framework te gebruiken, zie .NET Framework projecten.

De database-identiteit heeft toestemming nodig om verbinding te maken en om een tabel te maken, in te voegen en te selecteren.

Het project maken

Voer in een lege map deze commando's uit:

dotnet new web --framework net10.0 --name SqlClientWebQuickstart
cd SqlClientWebQuickstart
dotnet add package Microsoft.Data.SqlClient --version 7.1.1
dotnet add package Microsoft.Data.SqlClient.Extensions.Azure --version 7.1.1
dotnet user-secrets init

dotnet user-secrets init voegt een UserSecretsId toe aan het projectbestand. ASP.NET Core laadt gebruikersgeheimen alleen wanneer de app in de Development omgeving draait, wat de standaard is voor dotnet run.

Het extensiepakket levert de Microsoft Entra-authenticatiemodi van het stuurprogramma. Als je app alleen SQL-authenticatie gebruikt, kun je Microsoft.Data.SqlClient.Extensions.Azure weglaten. Als je beide pakketten gebruikt, houd dan hun versies hetzelfde.

Configureer de verbinding

Sla de verbindingsreeks op als ConnectionStrings:Quickstart in user secrets. Gebruikersgeheimen worden opgeslagen in je gebruikersprofiel, niet in de projectmap, dus ze worden niet ingecheckt in versiebeheer. Plaats geen wachtwoord of productieverbindingsreeks in appsettings.json.

Kies een van deze startpunten en vervang de placeholders. De dotnet user-secrets set commando's gebruiken enkele aanhalingstekens voor PowerShell en Bash. Gebruik in de opdrachtprompt dubbele aanhalingstekens, omdat de opdrachtprompt enkele aanhalingstekens opslaat als onderdeel van de sleutel en waarde.

Azure SQL with Microsoft Entra ID

Log in met een Microsoft Entra-identiteit die toegang heeft tot de database. Voor lokale ontwikkeling gebruik je een ontwikkelaarstool zoals de Azure CLI:

az login

Sla daarna de verbindingsreeks op. Kopieer de exacte server- en databasenamen uit de Azure SQL-database. Dezelfde verbindingsreeks werkt voor de SQL-database in Microsoft Fabric wanneer je de server- en databasenamen van het SQL-databaseitem gebruikt, zoals beschreven in de console quickstart.

dotnet user-secrets set 'ConnectionStrings:Quickstart' 'Server=tcp:<server>,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict;Connect Timeout=30'

Deze verbindingsreeks bevat geen secret. Active Directory Default gebruikt je ontwikkelaarsaanmelding lokaal. Wanneer je uitrolt naar Azure App Service of Azure Container Apps, verleen je de beheerde identiteit van de app toegang tot de database, verander je de waarde naar Authentication=Active Directory Managed Identity, en stel je deze als ConnectionStrings__Quickstart in in de configuratie van de host. Voor andere opties, zie Microsoft Entra-authenticatie met Microsoft.Data.SqlClient.

Lokale SQL Server met SQL-authenticatie

Sla de verbindingsreeks op voor een lokale ontwikkelinstantie die geen vertrouwd certificaat heeft. Gebruik enkele aanhalingstekens om te voorkomen dat PowerShell en Bash een $ teken in het wachtwoord interpreteren.

dotnet user-secrets set 'ConnectionStrings:Quickstart' 'Server=tcp:<server>,1433;Database=<database>;User ID=<user-id>;Password=<password>;Encrypt=true;TrustServerCertificate=true;Connect Timeout=30'

Caution

TrustServerCertificate=true Slaat servercertificaatvalidatie over. Gebruik het alleen met een lokale ontwikkelingsinstantie. Voor gedeelde of productie-SQL Server-instanties installeer je een certificaat dat de client vertrouwt en verwijder TrustServerCertificate=true. Zie Versleuteling en certificaatvalidatie in Microsoft.Data.SqlClientvoor meer informatie.

Code toevoegen

Vervang de inhoud van Program.cs met deze code:

using System.Data;
using Microsoft.Data.SqlClient;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<MessageStore>();

var app = builder.Build();

await app.Services.GetRequiredService<MessageStore>()
    .EnsureTableAsync(app.Lifetime.ApplicationStopping);

app.MapPost("/messages", async (
    NewMessage input, MessageStore store, CancellationToken cancellationToken) =>
{
    if (string.IsNullOrWhiteSpace(input.Text) || input.Text.Length > 200)
    {
        return Results.BadRequest("Text must be 1 to 200 characters.");
    }

    Message message = await store.AddAsync(input.Text, cancellationToken);
    return Results.Created($"/messages/{message.Id}", message);
});

app.MapGet("/messages/{id:int}", async (
    int id, MessageStore store, CancellationToken cancellationToken) =>
    await store.GetAsync(id, cancellationToken) is Message message
        ? Results.Ok(message)
        : Results.NotFound());

app.Run();

record NewMessage(string Text);

record Message(int Id, string Text, DateTimeOffset CreatedAt);

sealed class MessageStore(IConfiguration configuration)
{
    private readonly string _connectionString =
        configuration.GetConnectionString("Quickstart")
        ?? throw new InvalidOperationException(
            "Set the ConnectionStrings:Quickstart configuration value.");

    public async Task EnsureTableAsync(CancellationToken cancellationToken)
    {
        const string sql = """
            IF OBJECT_ID(N'dbo.SqlClientQuickstart', N'U') IS NULL
            BEGIN
                CREATE TABLE dbo.SqlClientQuickstart
                (
                    Id int IDENTITY(1, 1) PRIMARY KEY,
                    Message nvarchar(200) NOT NULL,
                    CreatedAt datetimeoffset NOT NULL
                        CONSTRAINT DF_SqlClientQuickstart_CreatedAt
                        DEFAULT sysdatetimeoffset()
                );
            END;
            """;

        await using var connection = new SqlConnection(_connectionString);
        await connection.OpenAsync(cancellationToken);
        await using var command =
            new SqlCommand(sql, connection) { CommandTimeout = 30 };
        await command.ExecuteNonQueryAsync(cancellationToken);
    }

    public async Task<Message> AddAsync(
        string text, CancellationToken cancellationToken)
    {
        const string sql = """
            INSERT INTO dbo.SqlClientQuickstart (Message)
            OUTPUT INSERTED.Id, INSERTED.Message, INSERTED.CreatedAt
            VALUES (@message);
            """;

        await using var connection = new SqlConnection(_connectionString);
        await connection.OpenAsync(cancellationToken);
        await using var command =
            new SqlCommand(sql, connection) { CommandTimeout = 30 };
        command.Parameters.Add("@message", SqlDbType.NVarChar, 200).Value = text;

        await using SqlDataReader reader =
            await command.ExecuteReaderAsync(cancellationToken);
        await reader.ReadAsync(cancellationToken);
        return new Message(
            reader.GetInt32(0), reader.GetString(1), reader.GetDateTimeOffset(2));
    }

    public async Task<Message?> GetAsync(
        int id, CancellationToken cancellationToken)
    {
        const string sql = """
            SELECT Id, Message, CreatedAt
            FROM dbo.SqlClientQuickstart
            WHERE Id = @id;
            """;

        await using var connection = new SqlConnection(_connectionString);
        await connection.OpenAsync(cancellationToken);
        await using var command =
            new SqlCommand(sql, connection) { CommandTimeout = 30 };
        command.Parameters.Add("@id", SqlDbType.Int).Value = id;

        await using SqlDataReader reader =
            await command.ExecuteReaderAsync(cancellationToken);
        return await reader.ReadAsync(cancellationToken)
            ? new Message(
                reader.GetInt32(0), reader.GetString(1), reader.GetDateTimeOffset(2))
            : null;
    }
}

De app uitvoeren

Start de app op een vaste poort:

dotnet run --urls http://localhost:5000

Bij het opstarten maakt de app de tabel aan als die niet bestaat. Wanneer de app klaar is, bevat de output deze regels:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development

Als de app de database niet kan bereiken, stopt hij bij het opstarten met een SqlException. Voor veelvoorkomende oorzaken, zie Probleemoplossing.

De API aanroepen

Laat de app draaien en open een tweede terminal. Voeg een bericht toe met een POST-verzoek, en lees het vervolgens terug via ID met een GET-verzoek. Als de tabel al rijen heeft, bijvoorbeeld van de console-quickstart, vervang 1 dan in het GET-verzoek door de id die je POST-verzoek teruggeeft.

Voor PowerShell:

Invoke-RestMethod -Method Post -Uri http://localhost:5000/messages -ContentType application/json -Body (@{ text = 'Hello from ASP.NET Core' } | ConvertTo-Json)
Invoke-RestMethod http://localhost:5000/messages/1

PowerShell formateert elke JSON-respons als een tabel. De eerste rij is het 201 Created antwoord op het POST-verzoek, en de tweede rij is het GET-antwoord:

id text                    createdAt
-- ----                    ---------
 1 Hello from ASP.NET Core 2026-10-21T00:04:43.3588978+00:00
 1 Hello from ASP.NET Core 2026-10-21T00:04:43.3588978+00:00

Windows PowerShell 5.1 toont createdAt als de string die de API teruggeeft. PowerShell 7 zet het om naar een datum in lokale tijd, zoals 10/20/2026 7:04:43 PM.

In Windows PowerShell curl is een alias voor Invoke-WebRequest, dat de curl-opties niet accepteert. Gebruik de PowerShell-commando's, of start curl.exe via de opdrachtprompt.

Voor de opdrachtprompt:

curl -X POST http://localhost:5000/messages -H "Content-Type: application/json" -d "{\"text\":\"Hello from ASP.NET Core\"}"
curl http://localhost:5000/messages/1

De opdrachtprompt behandelt enkele aanhalingstekens niet als aanhalingstekens, dus gebruikt het JSON-lichaam dubbele aanhalingstekens die met backslashes zijn ontsnapt. Elk commando geeft de JSON-respons weer:

{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-21T00:05:15.4936763+00:00"}
{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-21T00:05:15.4936763+00:00"}

Voor Bash:

curl -X POST http://localhost:5000/messages -H "Content-Type: application/json" -d '{"text":"Hello from ASP.NET Core"}'
curl http://localhost:5000/messages/1
{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-20T20:44:17.8634925+00:00"}
{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-20T20:44:17.8634925+00:00"}

Je ID's en tijdstempels verschillen. Als je eerst de console quickstart hebt uitgevoerd, lopen de ID's door vanaf die rijen. Een verzoek om een ID dat niet bestaat geeft 404 Not Found terug. Een leeg bericht geeft 400 Bad Request terug.

Druk op Ctrl+C in de eerste terminal om de app te stoppen.

Hoe de code werkt

  • De app registreert MessageStore als singleton. Het bevat alleen de verbindingsreeks, die het één keer uit IConfiguration leest. De verbinding blijft niet behouden.
  • Elke methode maakt een SqlConnection, opent het, voert één commando uit en ruimt het op met await using. Bij het opruimen wordt de fysieke verbinding teruggegeven aan de verbindingspool en hergebruikt het volgende verzoek deze. Connection pooling staat standaard aan, dus je hoeft het niet te configureren. Voor afstemmingsopties, zie SQL Server connection pooling met Microsoft.Data.SqlClient.
  • ASP.NET Core bindt de parameter CancellationToken aan de aanvraag. Als de client de verbinding verbreekt, annuleert het token het openen, het commando en het lezen.
  • De parameters @id en @message komen overeen met de kolomtypen en -grootten. De API valideert de berichtlengte voordat de API de waarde naar de database stuurt.
  • OUTPUT INSERTED.Id, INSERTED.Message, INSERTED.CreatedAt geeft de ingevoegde rij terug, inclusief de door de server gegenereerde ID en tijdstempel, zonder een tweede query.
  • In andere omgevingen leest ASP.NET Core dezelfde ConnectionStrings:Quickstart sleutel uit omgevingsvariabelen, zoals ConnectionStrings__Quickstart, of van een andere configuratieprovider, zoals Azure Key Vault.

Troubleshoot

Fout of symptoom Wat u moet controleren Meer informatie
Set the ConnectionStrings:Quickstart configuration value. De app vond de verbindingsreeks niet. Voer dotnet user-secrets list uit in de projectmap en controleer of de app in de Development-omgeving draait. Veilige opslag van app-geheimen tijdens ontwikkeling in ASP.NET Core
System.ArgumentException: Cannot find an authentication provider for 'ActiveDirectoryDefault' Bij de start De verbindingsreeks gebruikt een Active Directory authenticatiemodus, maar het project verwijst niet naar Microsoft.Data.SqlClient.Extensions.Azure. Voeg het pakket toe met dezelfde versie als Microsoft.Data.SqlClient. Microsoft Entra-authenticatie verplaatst zich in 7.0 naar een extensiepakket
SqlException Bij de start De app kon geen verbinding maken of de tabel aanmaken. Het foutnummer geeft de oorzaak aan, zoals 18456 voor een mislukte login. Probleemoplossing in de console quickstart
415 Unsupported Media Type Het verzoek stelt Content-Type: application/json niet in. Minimal APIs beknopte naslaggids
Cannot bind parameter 'Headers' Je voerde het curl-commando uit in Windows PowerShell, waarin curlInvoke-WebRequest uitvoert. Gebruik de PowerShell-opdrachten in De API aanroepen. Invoke-RestMethod
''' is an invalid start of a value Je voerde het Bash curl-commando uit in de opdrachtprompt, die de enkele aanhalingstekens als onderdeel van de body stuurt. Gebruik de opdrachtpromptcommando's in De API aanroepen. Roep de API aan

De hulpbronnen opschonen

Verwijder de tabel met een willekeurige query tool:

DROP TABLE IF EXISTS dbo.SqlClientQuickstart;

Verwijder de opgeslagen verbindingsreeks. Voer vanuit de projectmap uit:

dotnet user-secrets clear

Verwijder daarna de projectmap. Voer vanuit de oudermap het volgende commando uit in PowerShell:

Remove-Item -Recurse -Force SqlClientWebQuickstart

Voor Bash:

rm -rf SqlClientWebQuickstart

Volgende stappen