Предварительные требования
- .NET SDK 10. Это руководство проверено на .NET SDK 10.0.401, EF Core 10.0.12 и
Npgsql.EntityFrameworkCore.PostgreSQL10.0.3 (Npgsql 10.0.3). - Аккаунт ClickHouse Cloud
psqlдля создания базы данных. ОператорCREATE DATABASEтакже можно выполнить в консоли SQL.
Создание сервиса ClickHouse Managed Postgres
В консоли ClickHouse Cloud нажмите New service и выберите Postgres. Инстанс будет готов через несколько минут. Пошаговая инструкция приведена в кратком руководстве по началу работы.Получите сведения о подключении
Нажмите Подключение на левой боковой панели вашего сервиса. Оставьте выбранным вариант Directly, включите Use SSL и скопируйте пароль и имя хоста сервера. Затем нажмите Download CA certificate. Сертификат можно скачать и позже в разделе Settings → CA Certificate. Он уникален для вашего инстанса, поэтому Npgsql может с его помощью убедиться, что подключается именно к вашему серверу. В этом руководстве и приложение, и миграции EF Core подключаются к Postgres напрямую через порт5432. Приложение ASP.NET Core работает как долгоживущий процесс, а Npgsql уже обеспечивает в нём пул соединений (по умолчанию до 100 на одну строку подключения), поэтому дополнительный пулер не нужен. Если вы запускаете много инстансов приложения, см. раздел Использование PgBouncer.
В модальном окне Подключение нет вкладки для .NET, а Npgsql не принимает URL вида postgresql:// из вкладки url: вместо этого он использует строки подключения формата Keyword=Value. Возьмите значения из URL и сопоставьте их с ключевыми словами Npgsql:
Настройка проекта
Создайте проект ASP.NET Core, добавьте провайдер Npgsql для EF Core и пакет EF Core Design, необходимый на этапе разработки, а затем установите инструмент командной строкиdotnet ef:
Настройка соединения
Переместите загруженный CA‑сертификат в каталог проекта и переименуйте его вca-certificate.pem.
Создайте базу данных для приложения. Замените <PASSWORD> и хост на значения из модального окна Подключение:
appsettings.json, ни в систему контроля версий:
Development, которое dotnet run и dotnet ef используют по умолчанию. В продакшн-окружении вместо этого задайте переменную окружения ConnectionStrings__TodoDb.
С SSL Mode=VerifyFull Npgsql проверяет, что сертификат сервера подписан CA из Root Certificate и соответствует имени хоста. Относительный путь в Root Certificate Npgsql отсчитывает от текущего рабочего каталога — при запуске через dotnet run и dotnet ef это каталог проекта. Если вы запускаете приложение из другого места, укажите абсолютный путь.
Если CA указан неверно или отсутствует либо хост не соответствует сертификату (например, при подключении по IP-адресу), соединение завершается ошибкой
Exception while performing SSL handshake с вложенной ошибкой The remote certificate was rejected by the provided RemoteCertificateValidationCallback. Если файла Root Certificate не существует, вложенная ошибка будет Could not find file. Также учтите следующее:- По умолчанию Npgsql использует
SSL Mode=Prefer, аSSL Mode=Requireтоже не проверяет сертификат, даже если заданRoot Certificate. Всегда указывайтеSSL Mode=VerifyFull. - Npgsql считывает переменные окружения
PGSSLROOTCERTиPGPASSWORD, но неPGHOSTиPGSSLMODE. Поэтому одних только переменных с вкладки env в окне Подключение недостаточно.
Определение модели
Создайте файлTodo.cs с классом сущности:
Todo.cs
TodoDb.cs с классом DbContext:
TodoDb.cs
Program.cs. Этот код регистрирует TodoDb с провайдером Npgsql и сопоставляет каждой операции отдельную конечную точку. В существующем приложении достаточно лишь вызова AddDbContext с UseNpgsql:
Program.cs
/db/tls считывает данные из pg_stat_ssl для собственного сеанса приложения с базой данных — так можно убедиться, что соединение зашифровано.
Создание схемы
Сгенерируйте миграцию на основе модели и примените её:dotnet ef migrations add записывает миграцию в папку Migrations, а dotnet ef database update применяет её и фиксирует в таблице __EFMigrationsHistory. При первом запуске EF Core ещё до создания этой таблицы записывает в журнал ошибку SELECT из __EFMigrationsHistory — её можно игнорировать.
Перед применением миграций EF Core устанавливает блокировку, чтобы два развертывания не могли одновременно выполнять миграцию одной и той же базы данных. В Npgsql роль такой блокировки выполняет LOCK TABLE для __EFMigrationsHistory внутри транзакции миграции, а не рекомендательная (advisory) блокировка уровня сеанса, поэтому она снимается по завершении транзакции.
Запуск и проверка
Запустите приложение на порту3115:
DELETE возвращает 204 No Content, поэтому его строка пуста.
Убедитесь, что сеанс приложения с базой данных использует TLS:
guide_dotnet, затем public и выберите таблицу Todos. EF Core использует имена классов и свойств в качестве идентификаторов в кавычках, поэтому таблица называется "Todos", а столбцы — "Id", "Title" и т. д. В таблице осталась одна строка:
Использование PgBouncer
Npgsql открывает до 100 соединений на каждый инстанс приложения (Maximum Pool Size). Если суммарное число соединений от множества инстансов приближается к лимиту соединений Postgres, подключайте приложение через встроенный PgBouncer. Выберите via PgBouncer в модальном окне Подключение и укажите в строке подключения порт 6432:
- Подготовленные операторы: EF Core не подготавливает операторы, а автоматическая подготовка в Npgsql по умолчанию отключена (
Max Auto Prepare=0), поэтому запросы выполняются через безымянные операторы, которые работают с PgBouncer. Не меняйте эту конфигурацию. При работе через PgBouncer подготовленные операторы, созданные с помощьюMax Auto PrepareилиNpgsqlCommand.Prepare, время от времени завершаются ошибкой08P01: prepared statement did not exist(её предотвращаетNo Reset On Close=true), а после миграции, изменившей тип столбца, они продолжают завершаться ошибкойcached plan must not change result typeдаже на новых соединениях. Если вам нужны подготовленные операторы, подключайтесь напрямую. - Состояние сеанса: настройки, заданные с помощью
SET, включаяsearch_path, не сохраняются между транзакциями. Вместо этого используйтеSET LOCALвнутри транзакции. PgBouncer отклоняет ключевые слова строки подключенияSearch PathиOptionsс ошибкойunsupported startup parameter, аTimezoneиApplication Nameработают. - Миграции:
dotnet ef database updateтакже работает через PgBouncer, поскольку блокировка миграции — это блокировка таблицы, которая снимается по завершении её транзакции. - Проверка TLS:
pg_stat_sslописывает соединение между PgBouncer и Postgres, поэтому/db/tlsвозвращаетnone. При этом соединение вашего приложения с PgBouncer по-прежнему проверяется: с неверным CA‑сертификатом подключение завершится такой же ошибкой.
Дальнейшие шаги
- Подключение: строки подключения, PgBouncer и TLS
- Настройки: параметры Postgres и PgBouncer, например
max_connections - Реплики для чтения: перенаправление запросов только на чтение на реплику
- Безопасность: списки IP Access List и частное сетевое подключение