-
ClickHouseClient(рекомендуется): высокоуровневый потокобезопасный клиент, предназначенный для использования в качестве singleton. Предоставляет простой асинхронный API для запросов и массовых вставок. Лучше всего подходит для большинства приложений. -
ADO.NET (
ClickHouseDataSource,ClickHouseConnection,ClickHouseCommand): стандартные абстракции базы данных в .NET. Требуются для интеграции с ORM (Dapper, Linq2db) и в случаях, когда нужна совместимость с ADO.NET.ClickHouseBulkCopy— вспомогательный класс для эффективной вставки данных с использованием ADO.NET-соединения.ClickHouseBulkCopyустарел и будет удалён в одном из будущих релизов; вместо него используйтеClickHouseClient.InsertBinaryAsync.
Руководство по миграции
- Обновите файл
.csproj: укажите новое имя пакетаClickHouse.Driverи последнюю версию на NuGet. - Замените в кодовой базе все упоминания
ClickHouse.ClientнаClickHouse.Driver.
Поддерживаемые версии .NET
ClickHouse.Driver поддерживает следующие версии .NET:
- .NET 6.0
- .NET 8.0
- .NET 9.0
- .NET 10.0
Установка
Быстрый старт
Конфигурация
- Строка подключения: пары ключ/значение, разделённые точкой с запятой, которые задают хост, учётные данные для аутентификации и другие параметры подключения.
- Объект
ClickHouseClientSettings: строго типизированный объект конфигурации, который можно загрузить из файлов конфигурации или задать в коде.
Настройки подключения
Формат данных и сериализация
Управление сеансами
Флаг
UseSession включает сохранение сеанса на сервере, что позволяет использовать операторы SET и временные таблицы. Сеансы сбрасываются после 60 секунд бездействия (тайм-аут по умолчанию). Время жизни сеанса можно увеличить, задав настройку сеанса через команды ClickHouse или конфигурацию сервера.Класс ClickHouseConnection обычно поддерживает параллельную работу (несколько потоков могут выполнять запросы одновременно). Однако при включении флага UseSession для одного подключения в любой момент времени будет доступен только один активный запрос (это ограничение на стороне сервера).Безопасность
Конфигурация HTTP-клиента
Логирование и отладка
Пользовательские настройки и роли
Если вы задаёте пользовательские настройки через строку подключения, используйте префикс
set_, например: “set_max_threads=4”. Если вы используете объект ClickHouseClientSettings, префикс set_ указывать не нужно.Полный список доступных настроек см. здесь.Примеры строк подключения
Базовое подключение
С пользовательскими настройками ClickHouse
QueryOptions
QueryOptions позволяет переопределять настройки уровня клиента для отдельных запросов. Все свойства необязательны и переопределяют значения клиента по умолчанию только если они указаны.
Пример:
InsertOptions
InsertOptions дополняет QueryOptions настройками, специфичными для пакетных операций вставки через InsertBinaryAsync.
Все свойства
QueryOptions также доступны в InsertOptions.
Пример:
Пропуск запроса для определения схемы
InsertBinaryAsync перед каждой вставкой отправляет запрос SELECT ... WHERE 1=0, чтобы определить типы столбцов. В сценариях с высокой пропускной способностью эти накладные расходы можно исключить двумя способами:
Вариант 1: Явно указать типы столбцов
Если схема таблицы известна на этапе компиляции, передайте её напрямую через ColumnTypes. В этом случае запрос схемы вообще не отправляется:
UseSchemaCache = true, чтобы запросить схему один раз и повторно использовать её для последующих вставок через тот же экземпляр ClickHouseClient:
ColumnTypesимеет приоритет надUseSchemaCache. Если заданы оба параметра, используются явно указанные типы.- Кэш схемы не отслеживает изменения, внесённые командой
ALTER TABLE. Если вы изменяете схему таблицы, создайте новыйClickHouseClientили не используйтеUseSchemaCacheдля этой таблицы. - Кэш привязан к экземпляру
ClickHouseClient, а в качестве ключа используются (database, table). Разные подмножества столбцов одной и той же таблицы используют одну общую кэшированную схему.
ClickHouseClient
ClickHouseClient — рекомендуемый API для работы с ClickHouse. Он потокобезопасен, рассчитан на использование как singleton и самостоятельно управляет пулом HTTP-соединений.
Создание клиента
ClickHouseClient с помощью строки подключения или объекта ClickHouseClientSettings. Доступные параметры см. в разделе Конфигурация.
Сведения о вашем сервисе ClickHouse Cloud доступны в консоли ClickHouse Cloud.
Выберите сервис и нажмите Connect:
Выберите C#. Ниже отобразятся сведения о подключении.
Если вы используете самоуправляемый ClickHouse, сведения о подключении задаёт ваш администратор ClickHouse.
Использование строки подключения:
ClickHouseClientSettings:
IHttpClientFactory:
ClickHouseClient рассчитан на длительное использование и совместное использование во всём приложении. Создайте его один раз (обычно как singleton) и затем повторно используйте для всех операций с базой данных. Клиент сам управляет пулом HTTP-соединений.Выполнение запросов
ExecuteNonQueryAsync для команд, которые не возвращают результатов:
ExecuteScalarAsync, чтобы получить единственное значение:
Вставка данных
Параметризованные вставки
ExecuteNonQueryAsync. Типы параметров должны быть указаны в SQL с использованием синтаксиса {name:Type}:
Массовая вставка
InsertBinaryAsync для эффективной вставки большого количества строк. Метод передает данные в потоковом режиме в нативном бинарном формате строк ClickHouse, поддерживает параллельную загрузку батчей и позволяет избежать ошибок “URL too long”, которые могут возникать при параметризованных запросах.
InsertOptions:
- Перед вставкой клиент автоматически получает структуру таблицы с помощью
SELECT * FROM <table> WHERE 1=0. Передаваемые значения должны соответствовать типам целевых столбцов. Чтобы пропустить этот запрос, используйтеInsertOptions.ColumnTypesилиInsertOptions.UseSchemaCache. - Если
MaxDegreeOfParallelism > 1, батчи загружаются параллельно. Сеансы несовместимы с параллельной вставкой; либо отключите сеансы, либо задайтеMaxDegreeOfParallelism = 1. - Используйте
RowBinaryFormat.RowBinaryWithDefaultsвInsertOptions.Format, если хотите, чтобы сервер применял значения DEFAULT для столбцов, которые не были переданы.
Вставка POCO
object[] можно напрямую вставлять строго типизированные объекты POCO. Зарегистрируйте тип один раз, а затем передайте IEnumerable<T>:
Когда все сопоставленные свойства явно задают
Type, запрос для определения схемы полностью пропускается. Если явные типы указаны только у части свойств, драйвер возвращается к запросу для определения схемы для полного набора столбцов.
InsertBinaryAsync<T> поддерживает те же InsertOptions (батчинг, параллелизм, кэширование схемы), что и перегрузка object[].
В отличие от перегрузки
object[], InsertBinaryAsync<T> не принимает явный список столбцов. Столбцы определяются сопоставленными свойствами зарегистрированного типа. Чтобы управлять тем, какие столбцы вставляются, используйте [ClickHouseNotMapped], чтобы исключить свойства, или [ClickHouseColumn(Name = "...")], чтобы переименовать их.Если в InsertOptions задан ColumnTypes, он имеет приоритет над атрибутами POCO.Эволюция схемы
DEFAULT (или другими выражениями по умолчанию) сервер заполняет автоматически. Никаких изменений в коде или повторной регистрации не требуется.
Чтение данных
ExecuteReaderAsync для выполнения SELECT-запросов. Возвращаемый ClickHouseDataReader предоставляет типизированный доступ к столбцам результата с помощью таких методов, как GetInt64(), GetString() и GetFieldValue<T>().
Вызовите Read(), чтобы перейти к следующей строке. Метод возвращает false, когда строк больше не осталось. К столбцам можно обращаться по индексу (с нуля) или по имени столбца.
Параметры SQL
{parameter_name:DataType}.
Примеры:
SQL-параметры ‘bind’ передаются как параметры HTTP-запроса в URI, поэтому их слишком большое количество может привести к исключению “URL too long”. Чтобы избежать этого ограничения при массовой вставке данных, используйте
InsertBinaryAsync.Query ID
query_id, который можно использовать, чтобы получить данные из таблицы system.query_log или отменить долго выполняющиеся запросы. Вы можете указать собственный идентификатор запроса через QueryOptions:
Пользовательское сопоставление типов параметров
@ (например, WHERE id = @id) драйвер автоматически определяет тип ClickHouse по типу значения .NET. Например, int сопоставляется с Int32, а DateTime — с DateTime.
Чтобы переопределить эти значения по умолчанию, задайте ParameterTypeResolver в ClickHouseClientSettings. Это полезно, если вы хотите, чтобы все параметры DateTime использовали DateTime64(3) с точностью до миллисекунд, или чтобы для всех десятичных значений использовался определённый масштаб, без необходимости задавать ClickHouseType для каждого отдельного параметра.
Использование DictionaryParameterTypeResolver для простых сопоставлений типов:
IParameterTypeResolver для расширенных сценариев:
Если нужно определять тип по значению или имени, реализуйте интерфейс IParameterTypeResolver напрямую. Верните null, чтобы использовать определение типа по умолчанию:
QueryOptions.ParameterTypeResolver. Если он задан, он имеет приоритет над resolver на уровне клиента.
Приоритет разрешения типов:
Resolver — это один из шагов в цепочке приоритетов. От наивысшего приоритета к наименьшему:
- Явно заданный
ClickHouseTypeу параметра - Подсказка типа SQL из синтаксиса
{name:Type}в запросе IParameterTypeResolver(изQueryOptions.ParameterTypeResolverс откатом кClickHouseClientSettings.ParameterTypeResolver)- Встроенный вывод типов (
TypeConverter.ToClickHouseType)
ClickHouseConnection — настройки наследуются соединениями, созданными клиентом.
Прямая потоковая передача
ExecuteRawResultAsync, чтобы напрямую передавать результаты запроса в указанном формате, минуя средство чтения данных. Это удобно для экспорта данных в файлы или передачи в другие системы:
JSONEachRow, CSV, TSV, Parquet, Native. Все доступные варианты см. в документации по форматам.
Вставка из необработанного потока
InsertRawStreamAsync, чтобы вставлять данные напрямую из файловых потоков или потоков в памяти в таких форматах, как CSV, JSON, Parquet, или в любом поддерживаемом формате ClickHouse.
Вставка из CSV-файла:
Параметры, управляющие поведением ингестии данных, см. в документации по настройкам форматов.
Дополнительные примеры
ADO.NET
ClickHouseConnection, ClickHouseCommand и ClickHouseDataReader. Этот API необходим для интеграции с ORM (Dapper, Linq2db), а также в случаях, когда нужны стандартные абстракции базы данных .NET.
Управление жизненным циклом с ClickHouseDataSource
ClickHouseDataSource, чтобы обеспечить корректное управление жизненным циклом и использование пула соединений. DataSource внутренне использует один ClickHouseClient, и все соединения совместно используют его пул HTTP-соединений.
Использование ClickHouseCommand
ExecuteNonQueryAsync()— Для операторов INSERT, UPDATE, DELETE и DDL-операторовExecuteScalarAsync()— Возвращает первый столбец первой строкиExecuteReaderAsync()— ВозвращаетClickHouseDataReaderдля перебора результатов
Использование ClickHouseDataReader
ClickHouseDataReader обеспечивает типизированный доступ к результатам запроса:
Рекомендации
Время жизни соединений и пул соединений
ClickHouse.Driver использует System.Net.Http.HttpClient внутри. У HttpClient есть отдельный пул соединений для каждой конечной точки. В результате:
- Сеансы базы данных мультиплексируются через HTTP-соединения, которыми управляет пул соединений.
- HTTP-соединения автоматически переиспользуются пулом.
- Соединения могут оставаться активными даже после освобождения объектов
ClickHouseClientилиClickHouseConnection.
Обработка DateTime
-
По возможности используйте UTC. Храните временные метки в столбцах
DateTime('UTC')и используйтеDateTimeKind.Utcв коде. Это устраняет неоднозначность, связанную с часовыми поясами. -
Используйте
DateTimeOffsetдля явной работы с часовыми поясами. Он всегда представляет конкретный момент времени и содержит информацию о смещении. -
Указывайте часовой пояс в подсказках типов SQL. Если вы используете параметры со значениями DateTime
Unspecifiedдля столбцов не в UTC, указывайте часовой пояс прямо в SQL:
Асинхронные вставки
CustomSettings или строку подключения:
wait_for_async_insert):
Ключевые настройки:
Сеансы
- Временные таблицы (
CREATE TEMPORARY TABLE) - Сохранение контекста запроса между несколькими командами
- Настройки уровня сеанса (
SET max_threads = 4)
Поддерживаемые типы данных
ClickHouse.Driver поддерживает все типы данных ClickHouse. В таблицах ниже показано соответствие между типами ClickHouse и встроенными типами .NET при чтении данных из базы данных.
Сопоставление типов: чтение из ClickHouse
Целочисленные типы
Типы чисел с плавающей точкой
Десятичные типы
Преобразование типа Decimal регулируется настройкой UseCustomDecimals.
Логический тип
Строковые типы
По умолчанию столбцы
String и FixedString(N) возвращаются как string. Установите ReadStringsAsByteArrays=true в строке подключения, чтобы вместо этого считывать их как byte[]. Это полезно при хранении бинарных данных, которые могут быть не в корректной кодировке UTF-8.Типы даты и времени
ClickHouse хранит значения
DateTime и DateTime64 внутри как Unix-временные метки (секунды или доли секунды с начала эпохи Unix). Хотя хранение всегда выполняется в UTC, со столбцами может быть связан часовой пояс, который влияет на то, как значения отображаются и интерпретируются.
При чтении значений DateTime свойство DateTime.Kind устанавливается на основе часового пояса столбца:
Для столбцов не в UTC возвращаемый
DateTime представляет локальное время в этом часовом поясе. Используйте ClickHouseDataReader.GetDateTimeOffset(), чтобы получить DateTimeOffset с корректным смещением для этого часового пояса:
DateTime, а не DateTime('Europe/Amsterdam')) драйвер возвращает DateTime с Kind=Unspecified. Это позволяет сохранить локальное время в точности в том виде, в котором оно хранится, не делая предположений о часовом поясе.
Если для столбцов без явно заданных часовых поясов вам нужно поведение с учётом часового пояса, сделайте одно из следующего:
- Используйте явные часовые пояса в определениях столбцов:
DateTime('UTC')илиDateTime('Europe/Amsterdam') - Задайте часовой пояс самостоятельно после чтения.
Тип JSON
Возвращаемый тип для JSON-столбцов задаётся параметром
JsonReadMode:
-
Binary(по умолчанию): ВозвращаетSystem.Text.Json.Nodes.JsonObject. Обеспечивает структурированный доступ к JSON-данным, но специализированные типы ClickHouse (например, IP-адреса, UUID и большие decimal-значения) внутри структуры JSON преобразуются в строковое представление. -
String: Возвращает исходный JSON в видеstring. Сохраняет точное представление JSON из ClickHouse, что полезно, когда JSON нужно передать дальше без парсинга или если вы хотите самостоятельно выполнять десериализацию.
Другие типы
Типы Dynamic и Variant преобразуются в тип, соответствующий фактическому базовому типу в каждой строке.
Геометрические типы
Тип Geometry — это Variant, который может содержать любой из геометрических типов. Он будет преобразован в соответствующий тип.
Сопоставление типов: запись в ClickHouse
Целочисленные типы
Типы с плавающей точкой
Логический тип
Строковые типы
Типы даты и времени
Драйвер учитывает
DateTime.Kind при записи значений:
Значения
DateTimeOffset всегда сохраняют точный момент времени.
Пример: UTC DateTime (точный момент времени сохраняется)
DateTimeKind.Utc или DateTimeOffset во всех операциях с DateTime. Это гарантирует, что ваш код будет работать одинаково независимо от часового пояса сервера, клиента или столбца.
HTTP-параметры vs пакетная загрузка
Unspecified есть важное различие между привязкой HTTP-параметров и пакетной загрузкой:
Bulk Copy знает часовой пояс целевого столбца и корректно интерпретирует значения Unspecified в этом часовом поясе.
HTTP Parameters не знают часовой пояс столбца автоматически. Его необходимо указать в подсказке типа SQL:
Десятичные типы
Тип JSON
Поведение при записи JSON определяется настройкой
JsonWriteMode:
-
String(по умолчанию): Принимаетstring,JsonObject,JsonNodeили любой объект. Все входные данные сериализуются черезSystem.Text.Json.JsonSerializerи отправляются как JSON-строки для разбора на стороне сервера. Это самый гибкий режим, который работает без регистрации типов. -
Binary: Принимает только зарегистрированные типы POCO. На стороне клиента данные преобразуются в двоичный JSON-формат ClickHouse с полной поддержкой подсказок типов. Перед использованием необходимо вызватьconnection.RegisterJsonSerializationType<T>(). Запись значенийstringилиJsonNodeв этом режиме генерируетArgumentException.
Типизированные JSON-столбцы
JSON(id UInt64, price Decimal128(2))), драйвер использует их для сериализации значений с полным сохранением точности типов. Это позволяет сохранить точность для таких типов, как UInt64, Decimal, UUID и DateTime64, которая иначе могла бы теряться при сериализации в обычный JSON.
Сериализация POCO
JsonWriteMode:
Режим String (по умолчанию): POCO сериализуются через System.Text.Json.JsonSerializer. Регистрировать типы не требуется. Это самый простой вариант, и он работает с анонимными объектами.
Бинарный режим: POCO сериализуются с использованием бинарного JSON-формата драйвера с полной поддержкой подсказок типа. Перед использованием типы необходимо зарегистрировать с помощью connection.RegisterJsonSerializationType<T>(). Этот режим поддерживает пользовательские сопоставления путей с помощью атрибутов:
-
[ClickHouseJsonPath("path")]: Связывает свойство с пользовательским JSON-путём. Полезно для вложенных структур или когда имя свойства отличается от нужного JSON-ключа. Работает только в бинарном режиме. -
[ClickHouseJsonIgnore]: Исключает свойство из сериализации. Работает только в бинарном режиме.
UserId будет сопоставлено только с подсказкой, заданной как UserId, а не userid. Это соответствует поведению ClickHouse, где пути вроде userName и UserName могут сосуществовать как отдельные поля.
Ограничения (только для режима Binary):
- Типы POCO должны быть зарегистрированы для подключения с помощью
connection.RegisterJsonSerializationType<T>()до сериализации. Попытка сериализовать незарегистрированный тип вызывает исключениеClickHouseJsonSerializationException. - Для корректной сериализации свойств словарей и массивов/списков требуются подсказки типов в определении столбца. Без таких подсказок используйте режим String.
- Значения NULL в свойствах POCO записываются только в том случае, если для пути в определении столбца указана подсказка типа
Nullable(T). ClickHouse не допускает типыNullableвнутри динамических JSON-путей, поэтому свойства со значением null без подсказок пропускаются. - Атрибуты
ClickHouseJsonPathиClickHouseJsonIgnoreигнорируются в режиме String (они работают только в режиме Binary).
Другие типы
Геометрические типы
Не поддерживается при записи
Обработка вложенных типов
Nested(...)) можно читать и записывать как массивы.
Логирование и диагностика
Microsoft.Extensions.Logging и предоставляет легковесное логирование, которое можно включить при необходимости. Когда оно включено, драйвер выводит структурированные сообщения о событиях жизненного цикла соединения, выполнении команд, транспортных операциях и операциях массовой вставки. Логирование полностью опционально — приложения, в которых не настроен логгер, продолжают работать без дополнительной нагрузки.
Быстрый старт
Использование appsettings.json
Использование конфигурации в памяти
Категории и источники
Пример: Диагностика проблем с подключением
- Выбор фабрики HTTP-клиента (пул по умолчанию или одиночное соединение)
- Конфигурация HTTP-обработчика (SocketsHttpHandler или HttpClientHandler)
- Настройки пула соединений (MaxConnectionsPerServer, PooledConnectionLifetime и т. д.)
- Настройки тайм-аутов (ConnectTimeout, Expect100ContinueTimeout и т. д.)
- Настройка SSL/TLS
- События открытия и закрытия соединения
- Отслеживание идентификатора сеанса
Режим отладки: сетевая трассировка и диагностика
ClickHouse.Driver.Diagnostic.TraceHelper). События будут записываться в категорию ClickHouse.Driver.NetTrace. Предупреждение: это приведет к созданию чрезвычайно подробных журналов и повлияет на производительность. Включать режим отладки в продакшн не рекомендуется.
OpenTelemetry
System.Diagnostics.Activity. При включении драйвер создаёт спаны для операций с базой данных, которые можно экспортировать в системы обсервабилити, такие как Jaeger или сам ClickHouse (через OpenTelemetry Collector).
Включение трассировки
ActivitySource драйвера ClickHouse в конфигурацию OpenTelemetry:
Атрибуты спана
Параметры конфигурации
ClickHouseDiagnosticsOptions:
Настройка TLS
Пользовательская проверка сертификатов
HttpClient с настроенным обработчиком ServerCertificateCustomValidationCallback:
Важные моменты при использовании пользовательского HttpClient
- Автоматическая декомпрессия: Нужно включить
AutomaticDecompression, если сжатие не отключено (по умолчанию сжатие включено). - Тайм-аут простоя: Установите
PooledConnectionIdleTimeoutменьше значенияkeep_alive_timeoutсервера (10 секунд для ClickHouse Cloud), чтобы избежать ошибок подключения из-за полуоткрытых соединений.
Поддержка ORM
ClickHouseConnection). Чтобы корректно управлять временем жизни подключения, создавайте подключения через ClickHouseDataSource:
Dapper
ClickHouse.Driver работает с Dapper. Драйвер автоматически преобразует синтаксис Dapper @parameter в нативный для ClickHouse синтаксис {parameter:Type}, при этом типы выводятся автоматически на основе значений .NET.
Используйте ClickHouseDataSource для корректного управления временем жизни соединения:
Способы передачи параметров
DynamicParameters (из словаря или анонимного объекта):
Запросы в объекты POCO
Собственный синтаксис параметров ClickHouse
{param:Type}, а значения параметров передавайте через Dictionary<string, object>. Не используйте синтаксис @param и синтаксис {param:Type} одновременно для одного и того же параметра.
WHERE IN
WHERE id IN (@Ids1, @Ids2, @Ids3), а драйвер обрабатывает каждый развёрнутый параметр.
Функция has() в ClickHouse с параметром Array тоже работает:
Пользовательские обработчики типов
ITuple, BigInteger и ClickHouseDecimal, необходимо зарегистрировать обработчики при запуске:
Dapper.Contrib
GetAll<T>() и Get<T>(id) работают. Insert<T>() не работает — этот метод генерирует синтаксис SQL Server (SCOPE_IDENTITY, []). Вместо него рекомендуется использовать нативный метод InsertBinaryAsync клиента ClickHouseClient.
Ограничения
Linq2db
DataConnection, используя провайдер ClickHouse:
BulkCopyAsync для эффективной пакетной вставки.
Entity Framework Core
SaveChanges — всё это в привычных шаблонах EF Core.
- NuGet:
ClickHouse.EntityFrameworkCore - Source: GitHub
Этот провайдер активно развивается. Текущая версия поддерживает LINQ-запросы (включая JOIN, подзапросы и операции над множествами),
INSERT через SaveChanges / BulkInsertAsync, миграции с полной поддержкой DDL (CREATE / ALTER / DROP), а также настройку движка таблицы ClickHouse. UPDATE / DELETE не поддерживаются.Установка
Быстрый старт
DbContext, затем выполните запрос с помощью LINQ:
Поддерживаемые типы
Используйте
ClickHouseDecimal (из ClickHouse.Driver.Numerics) вместо decimal, если нужна полная точность столбцов Decimal128/Decimal256: decimal в .NET ограничен 28–29 значащими цифрами.
Поддерживаемые операции LINQ
Where, OrderBy, Take, Skip, Select, First, Single, Any, All, Count, Distinct, AsNoTracking
GROUP BY и агрегатные функции: GroupBy с Count, LongCount, Sum, Average, Min, Max — включая HAVING (.Where() после .GroupBy()), несколько агрегатных функций в одной проекции и OrderBy по результатам агрегации.
JOIN: Join (INNER), шаблоны GroupJoin/SelectMany (LEFT и CROSS). LEFT JOIN возвращает реальный null для строк без совпадений (см. семантику NULL в LEFT JOIN ниже).
Подзапросы: коррелированные Contains / IN, Any / EXISTS, All, а также скалярные подзапросы в проекциях.
Операции над множествами: Concat (→ UNION ALL), Union (→ UNION DISTINCT), Intersect, Except.
Встроенные локальные коллекции: JOIN и Contains с коллекциями в памяти (int[], List<T> и т. д.) преобразуются в последовательность UNION.
Строковые методы: Contains, StartsWith, EndsWith, IndexOf, Replace, Substring, Trim/TrimStart/TrimEnd, ToLower, ToUpper, Length, IsNullOrEmpty, Concat (и оператор +).
Математические функции: стандартные методы Math и MathF, преобразуемые в эквивалентные функции ClickHouse — арифметические, логарифмические, тригонометрические и вспомогательные функции.
Семантика NULL в LEFT JOIN
set_join_use_nulls=1 во все подключения, чтобы поведение JOIN соответствовало ожиданиям Entity Framework.
Если ваш сервер ClickHouse или профиль запрещает изменять эту настройку (например, профиль readonly=1), отключите это поведение с помощью:
0 / "" вместо == null.
Вставка данных
SaveChanges использует нативный API драйвера InsertBinaryAsync — кодирование RowBinary со сжатием GZip, что гораздо эффективнее параметризованного SQL:
Added в Unchanged, как и у любого другого поставщика EF Core.
Размер батча можно настроить (по умолчанию — 1000):
Пакетная вставка
BulkInsertAsync вместо SaveChanges. Это метод расширения для DbContext, который полностью обходит механизм отслеживания изменений EF Core, разрешение идентичности и управление состоянием — он напрямую вызывает InsertBinaryAsync драйвера с двоичным кодированием RowBinary и сжатием GZip.
Поэтому он хорошо подходит для загрузки больших наборов данных, когда после вставки отслеживание сущностей не требуется:
IEnumerable<T> — сущности обрабатываются последовательно, без загрузки всех данных в память. Возвращаемое значение — количество вставленных строк. Сущности не прикрепляются к DbContext после вставки, поэтому перехода состояния Added → Unchanged не происходит.
Перечисления
Enum8/Enum16 можно сопоставить со свойствами string или типами C# enum. При использовании перечислений C# провайдер автоматически преобразует значения перечисления в их строковое представление и обратно:
Пользовательские преобразования типов
ValueConverter в EF Core позволяет сопоставлять пользовательские типы с типами, которые уже поддерживает провайдер. Сам провайдер ваш пользовательский тип не видит — EF Core выполняет преобразование на границе.
Преобразование для отдельного свойства:
Аннотации типов столбцов
string, int, DateTime и т. д., провайдер автоматически определяет тип ClickHouse. Для параметризованных типов и типов-обёрток необходимо явно указать тип ClickHouse.
Использование аннотаций данных (атрибутов):
OnModelCreating:
Array(Nullable(Int32)) и LowCardinality(Nullable(String)) — провайдер автоматически снимает обёртки Nullable и LowCardinality на каждом уровне вложенности.
Столбцы Variant и Dynamic
Variant(T1, T2, ...) и Dynamic в .NET сопоставляются с object. Поскольку object — слишком общий тип для автоматического вывода типов, необходимо явно указать тип хранения через .HasColumnType():
string, ulong, ulong[]).
JSON-столбцы
Json в ClickHouse, сопоставляя его с System.Text.Json.Nodes.JsonNode (по умолчанию) или string (через автоматический ValueConverter):
SaveChanges, так и через BulkInsertAsync:
string, а для столбца — тип Json — ValueConverter будет применён автоматически:
- Пути JSON не транслируются —
entity.Data["name"]в LINQ не преобразуется в SQL-синтаксис ClickHousedata.name. Фильтруйте по не-JSON-столбцам и анализируйте JSON в памяти. - Семантика NULL — JSON type в ClickHouse возвращает
{}(пустой объект) для значений NULL, а не SQL NULL. - Точность целых чисел — ClickHouse хранит все целые числа в JSON как
Int64. При чтении черезJsonNodeиспользуйтеGetValue<long>(), а неGetValue<int>().
Движки таблиц
ToTable(name, t => ...). Если движок не настроен, провайдер по умолчанию использует MergeTree, а ORDER BY определяется на основе первичного ключа сущности.
Секции движка:
WithOrderBy, WithPartitionBy, WithPrimaryKey, WithSampleBy, WithTtl, WithSettings. Все они применяются к построителю движка, который возвращает HasXxxEngine().
Возможности на уровне столбца: HasCodec, HasTtl, HasComment, HasDefault — все они участвуют в миграциях.
Индексы пропуска данных — через HasIndex(...).HasSkippingIndexType(...):
Миграции
Ограничения миграций
Помимо миграций, провайдер также пока не поддерживает:
UPDATE/DELETE- Транзакции:
BeginTransaction— no-op. ClickHouse не поддерживает ACID-транзакции. - Трансляцию запросов с JSON-путём:
entity.Data["key"]в LINQ не транслируется в SQL-синтаксис ClickHousedata.key. Фильтруйте по не-JSON-столбцам, а JSON анализируйте в памяти.
Ограничения
Столбцы AggregateFunction
AggregateFunction(...) нельзя запрашивать или напрямую вставлять в них данные.
Чтобы выполнить вставку: