Snabbstart: Använd Microsoft.Data.SqlClient i en ASP.NET Core-app

I denna quickstart bygger du ett ASP.NET Core minimalt API med Microsoft.Data.SqlClient 7.1.1.

Du börjar med en tom mapp, .NET SDK och en SQL Server- eller Azure SQL-databas som du kan nå från din dator. Du avslutar med ett webb-API som lägger till ett meddelande i en tabell och läser tillbaka det via ID.

Under tiden gör appen följande:

  • Läser sin reťazec pripojenia från ASP.NET Core-konfigurationen. För lokal utveckling kommer värdet från användarhemligheter, så det förblir utanför din projektmapp.
  • Registrerar en dataklass med beroendeinjektion.
  • Öppnar och stänger och frigör en anslutning för varje förfrågan, vilket låter standardanslutningspoolen återanvända fysiska anslutningar.
  • Skickar förfrågans CancellationToken till varje databasanrop.

Appen använder samma dbo.SqlClientQuickstart tabell som Quickstart: Koppla upp och fråga med Microsoft.Data.SqlClient. Du kan göra antingen quickstart först.

Prerequisites

Nuvarande ASP.NET Core körs på .NET, inte .NET Framework. För att använda drivrutinen från .NET Framework, se .NET Framework-projekt.

Databasidentiteten behöver behörighet för att ansluta och för att skapa, infoga och välja från en tabell.

Skapa projektet

I en tom mapp, kör dessa kommandon:

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 lägger till en UserSecretsId i projektfilen. ASP.NET Core laddar användarhemligheter endast när appen körs i Development-miljön, vilket är standarden för dotnet run.

Tilläggspaketet tillhandahåller drivrutinens Microsoft Entra-autentiseringslägen. Om din app endast använder SQL-autentisering kan du utelämna Microsoft.Data.SqlClient.Extensions.Azure. När du använder båda paketen, se till att de har samma version.

Konfigurera anslutningen

Lagra reťazec pripojenia som ConnectionStrings:Quickstart i användarhemligheter. Användarhemligheter lagras i din användarprofil, inte i projektmappen, så de checkas inte in i versionshanteringen. Ange inte ett lösenord eller en produktionsanslutningssträng i appsettings.json.

Välj en av dessa startpunkter och byt ut platshållarna. Kommandona dotnet user-secrets set använder enkla citattecken för PowerShell och Bash. I kommandoprompten, använd dubbla citattecken istället, eftersom kommandoprompten lagrar enkla citattecken som en del av nyckeln och värdet.

Azure SQL with Microsoft Entra ID

Logga in med en Microsoft Entra-identitet som har tillgång till databasen. För lokal utveckling, använd ett utvecklarverktyg som Azure CLI:

az login

Sedan lagra anslutningssträngen. Kopiera exakt server- och databasnamnen från Azure SQL-databasen. Samma reťazec pripojenia fungerar för SQL-databasen i Microsoft Fabric när du använder server- och databasnamnen från SQL-databasen, som beskrivs i konsolens snabbstart.

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

Denna anslutningssträng innehåller ingen hemlig nyckel. služba Active Directory Default använder din utvecklarinloggning lokalt. När du distribuerar till Azure App Service eller Azure Container Apps, ge appens hanterade identitet åtkomst till databasen, ändra värdet till Authentication=služba Active Directory Managed Identity, och ställ in det i värdens konfiguration som ConnectionStrings__Quickstart. För andra alternativ, se Microsoft Entra-autentisering med Microsoft. Data.SqlClient.

Lokal SQL Server med SQL-autentisering

Lagra reťazec pripojenia för en lokal utvecklingsinstans som inte har ett betrott certifikat. Använd enkla citattecken för att förhindra att PowerShell och Bash expanderar ett $ tecken i lösenordet.

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 Hoppar över validering av servercertifikat. Använd det endast med en lokal utvecklingsinstans. För delade eller produktions-SQL Server-instanser, installera ett certifikat som klienten litar på och ta bort TrustServerCertificate=true. Mer information finns i Kryptering och certifikatverifiering i Microsoft.Data.SqlClient.

Lägg till koden

Ersätt innehållet i Program.cs med den här koden:

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;
    }
}

Kör appen

Starta appen på en fast port:

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

Vid uppstart skapar appen tabellen om den inte finns. När appen är klar innehåller utdata dessa rader:

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

Om appen inte kan nå databasen stannar den vid uppstart och visar SqlException. För vanliga felorsaker, se Felsökning.

Anropa API:et

Låt appen vara igång och öppna en andra terminal. Lägg till ett meddelande med en POST-förfrågan och läs sedan tillbaka det med ID och en GET-förfrågan. Om tabellen redan har rader, till exempel från konsolens snabbstart, ersätt 1 i GET-förfrågan med det id-värde som din POST-förfrågan returnerar.

För 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 formaterar varje JSON-svar som en tabell. Den första raden är svaret 201 Created på POST-förfrågan, och den andra raden är GET-svaret:

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 visar createdAt som den sträng som API:et returnerar. PowerShell 7 konverterar det till ett datum i lokal tid, såsom 10/20/2026 7:04:43 PM.

I Windows PowerShell curl är ett alias för Invoke-WebRequest, som inte accepterar curl-alternativen. Använd PowerShell-kommandona eller kör curl.exe från kommandoprompten.

För kommandoprompt:

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

Kommandoprompten behandlar inte enkla citattecken som citattecken, så JSON-kroppen använder dubbla citattecken som föregås av omvänt snedstreck. Varje kommando skriver ut JSON-svaret:

{"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"}

För 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"}

Dina ID:n och tidsstämplar skiljer sig åt. Om du körde snabbstarten för konsolen först fortsätter ID:n från dess rader. En begäran om ett ID som inte existerar returnerar 404 Not Found. Ett tomt meddelande returnerar 400 Bad Request.

Tryck Ctrl+C i den första terminalen för att stoppa appen.

Så här fungerar koden

  • Appen registrerar MessageStore som en singleton. Den innehåller endast reťazec pripojenia, som den läser från IConfiguration en gång. Den håller inte kvar anslutningen.
  • Varje metod skapar en SqlConnection, öppnar den, kör ett kommando och frigör den med await using. När objektet frigörs returneras den fysiska anslutningen till anslutningspoolen, och nästa begäran återanvänder den. Anslutningspooling är påslagen som standard, så du behöver inte konfigurera det. För justeringsalternativ, se SQL Server connection pooling with Microsoft.Data.SqlClient.
  • ASP.NET Core binder parametern CancellationToken till begäran. Om klienten kopplas bort, avbryts öppningen, kommandot och läsningen av token.
  • Parametrarna @id och @message stämmer överens med kolumntyper och storlekar. API:et validerar meddelandelängden innan det skickar värdet till databasen.
  • OUTPUT INSERTED.Id, INSERTED.Message, INSERTED.CreatedAt returnerar den insatta raden, inklusive servergenererat ID och tidsstämpel, utan en andra fråga.
  • I andra miljöer läser ASP.NET Core samma ConnectionStrings:Quickstart nyckel från miljövariabler, såsom ConnectionStrings__Quickstart, eller från en annan konfigurationsleverantör, såsom Azure Key Vault.

Troubleshoot

Fel eller symptom Vad du bör kontrollera Mer information
Set the ConnectionStrings:Quickstart configuration value. Appen hittade inte anslutningssträngen. Kör dotnet user-secrets list i projektmappen och kontrollera att appen körs i miljön Development . Säkerhetslagring av apphemligheter under utveckling i ASP.NET Core
System.ArgumentException: Cannot find an authentication provider for 'ActiveDirectoryDefault' Vid startup Anslutningssträngen använder ett služba Active Directory-autentiseringsläge, men projektet refererar inte till Microsoft.Data.SqlClient.Extensions.Azure. Lägg till paketet med samma version som Microsoft.Data.SqlClient. Microsoft Entra-autentisering flyttar till ett tilläggspaket i 7.0
SqlException vid start Appen kunde inte ansluta eller skapa tabellen. Felnumret identifierar orsaken, till exempel 18456 för en misslyckad inloggning. Felsök i konsolens snabbstart
415 Unsupported Media Type Begäran anger inte Content-Type: application/json. Snabbreferens för minimala API:er
Cannot bind parameter 'Headers' Du körde curl-kommandot i Windows PowerShell, där curl kör Invoke-WebRequest. Använd PowerShell-kommandona i avsnittet Call the API. Invoke-RestMethod
''' is an invalid start of a value Du körde Bash curl-kommandot i kommandoprompten, som skickar de enkla citattecknen som en del av brödtexten. Använd kommandona i Kommandotolken i Anropa API:et. Anropa API:t

Rensa resurser

Ta bort tabellen med valfritt frågeverktyg:

DROP TABLE IF EXISTS dbo.SqlClientQuickstart;

Ta bort den lagrade anslutningssträngen. Från projektmappen, kör:

dotnet user-secrets clear

Ta sedan bort projektmappen. Från föräldramappen kör du följande kommando i PowerShell:

Remove-Item -Recurse -Force SqlClientWebQuickstart

För Bash:

rm -rf SqlClientWebQuickstart

Nästa steg