Быстрый старт: используйте Microsoft. Data.SqlClient в приложении ASP.NET Core

В этом быстром старте вы создаёте минимальный API ASP.NET Core с Microsoft.Data.SqlClient 7.1.1.

Вы начинаете с пустой папки, .NET SDK и базы данных SQL Server или Azure SQL, к которой можно получить доступ с компьютера. Вы заканчиваете веб-API, который добавляет сообщение в таблицу и читает его по ID.

По пути приложение:

  • Читает свою строку подключения из конфигурации ASP.NET Core. Для локальной разработки значение берется из пользовательских секретов, поэтому оно не попадает в папку проекта.
  • Регистрирует data class с помощью инъекции зависимостей.
  • Открывает и закрывает соединение для каждого запроса, что позволяет пулу соединений по умолчанию повторно использовать физические соединения.
  • Передаёт CancellationToken запроса в каждый вызов базы данных.

Приложение использует ту же dbo.SqlClientQuickstart таблицу, что и в Quickstart: Connect and query with Microsoft.Data.SqlClient. Можно сначала выполнить любой из двух вариантов быстрого запуска.

Prerequisites

Текущий ASP.NET Core работает на .NET, а не на .NET Framework. Чтобы использовать драйвер из .NET Framework, см. проекты .NET Framework.

Для удостоверения базы данных необходимы разрешения на подключение, а также на создание таблицы, вставку данных в таблицу и выборку данных из таблицы.

Создание проекта

В пустой папке выполните следующие команды:

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 добавляет UserSecretsId в файл проекта. ASP.NET Core загружает пользовательские секреты только тогда, когда приложение работает в среде Development, которая используется по умолчанию для dotnet run.

Пакет расширения предоставляет драйверу режимы аутентификации Microsoft Entra. Если ваше приложение использует только SQL-аутентификацию, вы можете опустить Microsoft.Data.SqlClient.Extensions.Azure. Когда используете оба пакета, оставляйте их версии одинаковыми.

Настройте соединение

Храните строка подключения как ConnectionStrings:Quickstart в пользовательских секретах. Пользовательские секреты хранятся в вашем профиле пользователя, а не в папке проекта, поэтому они не фиксируются в системе контроля версий. Не вставляйте пароль или строку подключения к рабочей среде в appsettings.json.

Выберите одну из этих отправных точек и замените заполнители. Эти команды dotnet user-secrets set используют одиночные кавычки для PowerShell и Bash. В Командной строке используйте двойные кавычки, потому что Командная строка сохраняет одинарные кавычки как часть ключа и значения.

Azure SQL with Microsoft Entra ID

Войдите с идентификатором Microsoft Entra, имеющим доступ к базе данных. Для локальной разработки используйте инструмент разработчика, например Azure CLI:

az login

Затем храните строку подключения. Скопируйте точные имена сервера и базы данных из базы данных Azure SQL. Та же строка подключения работает для базы данных SQL в Microsoft Fabric, когда вы используете имена сервера и базы данных из элемента базы данных SQL, как описано в кратком руководстве по консоли.

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

Эта строка подключения не содержит секрета. Active Directory Default локально использует ваш вход разработчика. При развертывании в Служба приложений Azure или Контейнеры приложений Azure предоставьте управляемой идентификации приложения доступ к базе данных, измените значение на Authentication=Active Directory Managed Identity и установите его в конфигурации хоста как ConnectionStrings__Quickstart. Для других вариантов см. аутентификация Microsoft Entra с Microsoft. Data.SqlClient.

Локальный SQL Server с SQL-аутентификацией

Сохранить строка подключения для локального экземпляра разработки, у которого нет доверенного сертификата. Используйте одиночные кавычки, чтобы не дать PowerShell и Bash расширять символ $ в пароле.

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 пропускает проверку сертификатов сервера. Используйте его только с локальным экземпляром разработки. Для общих или производственных экземпляров SQL Server установите сертификат, которому клиент доверяет, и удалите TrustServerCertificate=true. Для получения дополнительной информации см. Шифрование и проверка сертификатов в Microsoft.Data.SqlClient.

Добавление кода

Замените содержимое Program.cs на следующий код:

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

Запуск приложения

Запустите приложение на фиксированном порте:

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

При запуске приложение создаёт таблицу, если её нет. Когда приложение готово, вывод включает следующие строки:

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

Если приложение не может получить доступ к базе данных, оно останавливается при запуске с SqlException. Общие причины см. в разделе «Устранение неполадок».

Вызов API

Оставьте приложение включённым и откройте второй терминал. Добавьте сообщение с запросом POST, а затем прочитайте его по ID с помощью запроса GET. Если в таблице уже есть строки, например, из консольного quickstart, замените 1 в GET-запросе на id, который возвращает ваш POST-запрос.

Для 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 форматирует каждый ответ JSON в виде таблицы. Первая строка — 201 Created это ответ на запрос POST, а вторая — ответ GET:

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 отображает createdAt как строку, которую возвращает API. PowerShell 7 преобразует его в дату по местному времени, например 10/20/2026 7:04:43 PM.

В Windows PowerShell curl — это псевдоним для Invoke-WebRequest, который не принимает параметры curl. Используйте команды PowerShell или запускайте curl.exe из командной строки.

Для командной строки:

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

Командная строка не рассматривает одиночные кавычки как символы кавычки, поэтому тело JSON использует двойные кавычки с обратными косыми чертами. Каждая команда печатает ответ JSON:

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

Для 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"}

Ваши идентификаторы и временные метки различаются. Если сначала запустить краткое руководство по консоли, идентификаторы продолжаются с его строк. Запрос на идентификатор, которого не существует, возвращает 404 Not Found. Пустое сообщение возвращает 400 Bad Request.

Нажмите Ctrl+C в первом терминале, чтобы остановить приложение.

Как работает код

  • Приложение регистрирует MessageStore как синглтон. Он содержит только строку подключения, которую он считывает из IConfiguration один раз. Она не удерживает соединение.
  • Каждый метод создаёт SqlConnection, открывает её, выполняет одну команду и освобождает её с помощью await using. Освобождение возвращает физическое соединение в пул соединений, и следующий запрос использует его повторно. Пул соединений по умолчанию включён, так что его настраивать не нужно. Для вариантов настройки см. пул соединений SQL Server с Microsoft.Data.SqlClient.
  • ASP.NET Core связывает параметр CancellationToken с запросом. Если клиент отключается, токен отменяет открытие, команду и чтение.
  • Параметры @id и @message соответствуют типам и размерам столбцов. API проверяет длину сообщения перед тем, как отправить значение в базу данных.
  • OUTPUT INSERTED.Id, INSERTED.Message, INSERTED.CreatedAt возвращает вставленную строку, включая серверный идентификатор и временную метку, без второго запроса.
  • В других условиях ASP.NET Core считывает тот же ключ ConnectionStrings:Quickstart из переменных среды, таких как ConnectionStrings__Quickstart, или от другого поставщика конфигурации, например Azure Key Vault.

Troubleshoot

Ошибка или симптом Что требуется проверить Дополнительная информация
Set the ConnectionStrings:Quickstart configuration value. Приложение не нашло строка подключения. Запустите dotnet user-secrets list в папке проекта и проверьте, работает ли приложение в среде Development. Безопасное хранилище секретов приложений в процессе разработки в ASP.NET Core
System.ArgumentException: Cannot find an authentication provider for 'ActiveDirectoryDefault' при запуске Строка строка подключения использует режим аутентификации Active Directory, но в проекте нет ссылки на Microsoft.Data.SqlClient.Extensions.Azure. Добавьте пакет той же версии, что и Microsoft.Data.SqlClient. Аутентификация Microsoft Entra переходит в пакет расширения в версии 7.0
SqlException при запуске Приложение не смогло подключиться или создать таблицу. Номер ошибки позволяет определить причину, например, 18456 для неудачного входа. Устранение неполадок в кратком руководстве по консоли
415 Unsupported Media Type Запрос не устанавливает Content-Type: application/json. Краткий справочник по минимальным API
Cannot bind parameter 'Headers' Вы запустили команду curl в Windows PowerShell, в которой curl запускает Invoke-WebRequest. Используйте команды PowerShell в Call the API. Invoke-RestMethod
''' is an invalid start of a value Вы запустили команду Bash curl в командной строке, которая отправляет одинарные кавычки как часть тела запроса. Используйте команды Командной строки в Call the API. Вызовите API

Очистите ресурсы

Удалите таблицу с помощью любого инструмента запросов:

DROP TABLE IF EXISTS dbo.SqlClientQuickstart;

Удалите сохранённую строку подключения. Из папки проекта запустите:

dotnet user-secrets clear

Затем удалите папку проекта. Из родительской папки выполните следующую команду в PowerShell:

Remove-Item -Recurse -Force SqlClientWebQuickstart

Для Bash:

rm -rf SqlClientWebQuickstart

Дальнейшие действия