-
ClickHouseClient(recomendado): um cliente de alto nível, thread-safe, projetado para uso como singleton. Fornece uma API assíncrona simples para consultas e inserções em massa. Ideal para a maioria das aplicações. -
ADO.NET (
ClickHouseDataSource,ClickHouseConnection,ClickHouseCommand): abstrações padrão de banco de dados do .NET. Necessário para integração com ORM (Dapper, Linq2db) e quando você precisa de compatibilidade com ADO.NET.ClickHouseBulkCopyé uma classe auxiliar para inserir dados com eficiência usando uma conexão ADO.NET.ClickHouseBulkCopyfoi descontinuado e será removido em um lançamento futuro; useClickHouseClient.InsertBinaryAsyncno lugar.
Guia de migração
- Atualize o arquivo
.csprojcom o novo nome do pacoteClickHouse.Drivere a versão mais recente no NuGet. - Atualize todas as referências a
ClickHouse.ClientparaClickHouse.Driverno seu código.
Versões compatíveis do .NET
ClickHouse.Driver oferece suporte às seguintes versões do .NET:
- .NET 6.0
- .NET 8.0
- .NET 9.0
- .NET 10.0
Instalação
Início rápido
Configuração
- String de conexão: pares de chave/valor separados por ponto e vírgula que especificam o host, as credenciais de autenticação e outras opções de conexão.
- Objeto
ClickHouseClientSettings: um objeto de configuração fortemente tipado que pode ser carregado de arquivos de configuração ou definido no código.
Configurações de conexão
Formato e serialização de dados
Gerenciamento de sessão
O sinalizador
UseSession habilita a persistência da sessão do servidor, permitindo usar instruções SET e tabelas temporárias. As sessões serão redefinidas após 60 segundos de inatividade (timeout padrão). A duração da sessão pode ser estendida definindo configurações de sessão por meio de instruções do ClickHouse ou da configuração do servidor.A classe ClickHouseConnection normalmente permite operação paralela (várias threads podem executar consultas concorrentemente). No entanto, habilitar o sinalizador UseSession limitará isso a uma consulta ativa por conexão a qualquer momento (esta é uma limitação do servidor).Segurança
Configuração do cliente HTTP
Logging e depuração
Configurações personalizadas e roles
Ao usar uma string de conexão para definir configurações personalizadas, use o prefixo
set_, por exemplo, “set_max_threads=4”. Ao usar um objeto ClickHouseClientSettings, não use o prefixo set_.Para ver a lista completa de configurações disponíveis, consulte aqui.Exemplos de string de conexão
Conexão básica
Com configurações personalizadas do ClickHouse
QueryOptions
QueryOptions permite substituir configurações do cliente individualmente para cada consulta. Todas as propriedades são opcionais e só substituem os padrões do cliente quando especificadas.
Exemplo:
InsertOptions
InsertOptions estende QueryOptions com configurações específicas para operações de inserção em massa via InsertBinaryAsync.
Todas as propriedades de
QueryOptions também estão disponíveis em InsertOptions.
Exemplo:
Ignorando a consulta de sondagem do esquema
InsertBinaryAsync envia uma consulta SELECT ... WHERE 1=0 antes de cada inserção para identificar os tipos das colunas. Em cenários de alta taxa de transferência, você pode eliminar essa sobrecarga de duas formas:
Opção 1: Informe explicitamente os tipos das colunas
Quando você conhece o esquema da tabela em tempo de compilação, passe-o diretamente por meio de ColumnTypes. Nenhuma consulta de esquema é enviada:
UseSchemaCache = true para consultar o esquema uma única vez e reutilizá-lo nas inserções subsequentes na mesma instância do ClickHouseClient:
ColumnTypestem prioridade sobreUseSchemaCache. Se ambos estiverem definidos, os tipos explícitos serão usados.- O cache de esquema não detecta alterações feitas com
ALTER TABLE. Se você modificar o esquema da tabela, crie um novoClickHouseClientou evite usarUseSchemaCachepara essa tabela. - O cache tem escopo na instância de
ClickHouseCliente é indexado por (banco de dados, tabela). Diferentes subconjuntos de colunas da mesma tabela compartilham um único esquema em cache.
ClickHouseClient
ClickHouseClient é a API recomendada para interagir com o ClickHouse. Ela é thread-safe, foi projetada para uso como singleton e gerencia internamente um pool de conexões HTTP.
Criando um cliente
ClickHouseClient com uma string de conexão ou um objeto ClickHouseClientSettings. Consulte a seção Configuração para conhecer as opções disponíveis.
Os detalhes do seu serviço do ClickHouse Cloud estão disponíveis no console do ClickHouse Cloud.
Selecione um serviço e clique em Connect:
Escolha C#. Os detalhes da conexão são exibidos abaixo.
Se você estiver usando ClickHouse autogerenciado, os detalhes da conexão serão definidos pelo administrador do ClickHouse.
Usando uma string de conexão:
ClickHouseClientSettings:
IHttpClientFactory:
ClickHouseClient foi projetado para ter longa vida útil e ser compartilhado em toda a aplicação. Crie-o uma única vez (normalmente como um singleton) e reutilize-o em todas as operações do banco de dados. O cliente gerencia internamente o pool de conexões HTTP.Executando consultas
ExecuteNonQueryAsync para instruções que não retornam resultados:
ExecuteScalarAsync para obter um único valor:
Inserção de dados
Inserções parametrizadas
ExecuteNonQueryAsync. Os tipos dos parâmetros devem ser especificados no SQL usando a sintaxe {name:Type}:
Inserção em massa
InsertBinaryAsync para inserir grandes volumes de linhas com eficiência. Ele transmite os dados usando o formato binário nativo de linhas do ClickHouse, oferece suporte ao envio paralelo de lotes e evita erros de “URL muito longa” que podem ocorrer com consultas parametrizadas.
InsertOptions:
- O cliente obtém automaticamente a estrutura da tabela por meio de
SELECT * FROM <table> WHERE 1=0antes da inserção. Os valores fornecidos devem corresponder aos tipos das colunas de destino. Para ignorar essa consulta, useInsertOptions.ColumnTypesouInsertOptions.UseSchemaCache. - Quando
MaxDegreeOfParallelism > 1, os lotes são enviados em paralelo. As sessões não são compatíveis com inserção em paralelo; desative as sessões ou definaMaxDegreeOfParallelism = 1. - Use
RowBinaryFormat.RowBinaryWithDefaultsemInsertOptions.Formatse quiser que o servidor aplique valores DEFAULT às colunas não fornecidas.
Inserções com POCO
object[], você pode inserir diretamente objetos POCO com tipagem forte. Registre o tipo uma vez e, em seguida, passe IEnumerable<T>:
Quando todas as propriedades mapeadas especificam um
Type explícito, a consulta de sondagem do esquema é ignorada por completo. Quando apenas algumas propriedades têm tipos explícitos, o driver recorre à consulta de sondagem do esquema para o conjunto completo de colunas.
InsertBinaryAsync<T> oferece suporte às mesmas InsertOptions (batching, paralelismo, cache de esquema) que a sobrecarga object[].
Diferentemente da sobrecarga
object[], InsertBinaryAsync<T> não aceita uma lista explícita de colunas. As colunas são determinadas pelas propriedades mapeadas do tipo registrado. Para controlar quais colunas são inseridas, use [ClickHouseNotMapped] para excluir propriedades ou [ClickHouseColumn(Name = "...")] para renomeá-las.Se ColumnTypes estiver definido em InsertOptions, eles substituirão os atributos do POCO.Evolução do esquema
DEFAULT (ou outras expressões padrão) são preenchidas automaticamente pelo servidor. Não é necessário alterar o código nem fazer um novo registro.
Lendo dados
ExecuteReaderAsync para executar consultas SELECT. O ClickHouseDataReader retornado fornece acesso tipado às colunas do resultado por meio de métodos como GetInt64(), GetString() e GetFieldValue<T>().
Chame Read() para avançar para a próxima linha. Ele retorna false quando não há mais linhas. Acesse as colunas pelo índice (baseado em 0) ou pelo nome da coluna.
Parâmetros SQL
{parameter_name:DataType}.
Exemplos:
Os parâmetros SQL de ‘bind’ são passados como parâmetros de consulta do URI HTTP, portanto o uso excessivo deles pode resultar em uma exceção de “URL too long”. Use
InsertBinaryAsync para inserção de dados em massa e evitar essa limitação.ID da consulta
query_id único, que pode ser usado para obter dados da tabela system.query_log ou cancelar consultas de longa execução. Você pode especificar um ID de consulta personalizado por meio de QueryOptions:
Mapeamento personalizado de tipos de parâmetro
@ (por exemplo, WHERE id = @id), o driver infere automaticamente o tipo do ClickHouse com base no tipo de valor do .NET. Por exemplo, int é mapeado para Int32, e DateTime é mapeado para DateTime.
Para substituir esses padrões, defina ParameterTypeResolver em ClickHouseClientSettings. Isso é útil quando você quer que todos os parâmetros DateTime usem DateTime64(3) para precisão de milissegundos ou que todos os decimais usem uma escala específica, sem precisar definir ClickHouseType em cada parâmetro individualmente.
Usando DictionaryParameterTypeResolver para mapeamentos simples de tipo:
IParameterTypeResolver personalizado para cenários avançados:
Para resolução com base no valor ou no nome, implemente diretamente a interface IParameterTypeResolver. Retorne null para usar a inferência padrão:
QueryOptions.ParameterTypeResolver. Quando definido, ele tem precedência sobre o resolver no nível do cliente.
Precedência da resolução de tipos:
O resolver é uma etapa em uma cadeia de precedência. Da maior para a menor prioridade:
ClickHouseTypeexplícito definido no parâmetro- Type hint de SQL da sintaxe
{name:Type}na consulta IParameterTypeResolver(deQueryOptions.ParameterTypeResolver, com fallback paraClickHouseClientSettings.ParameterTypeResolver)- Inferência de tipo integrada (
TypeConverter.ToClickHouseType)
ClickHouseConnection — as configurações são herdadas pelas conexões criadas a partir do cliente.
Fluxo bruto
ExecuteRawResultAsync para transmitir diretamente os resultados da consulta em um formato específico, sem passar pelo leitor de dados. Isso é útil para exportar dados para arquivos ou repassá-los a outros sistemas:
JSONEachRow, CSV, TSV, Parquet, Native. Consulte a documentação sobre formatos para ver todas as opções.
Inserção bruta via stream
InsertRawStreamAsync para inserir dados diretamente de streams de arquivo ou de memória em formatos como CSV, JSON, Parquet ou qualquer formato compatível do ClickHouse.
Inserir de um arquivo CSV:
Consulte a documentação das configurações de formato para ver as opções de controle do comportamento da ingestão de dados.
Mais exemplos
ADO.NET
ClickHouseConnection, ClickHouseCommand e ClickHouseDataReader. Essa API é necessária para a integração com ORMs (Dapper, Linq2db) e quando você precisa das abstrações padrão de banco de dados do .NET.
Gerenciamento do ciclo de vida com ClickHouseDataSource
ClickHouseDataSource para garantir o gerenciamento adequado do ciclo de vida e o uso de pool de conexões. A DataSource gerencia internamente um único ClickHouseClient, e todas as conexões compartilham seu pool de conexões HTTP.
Usando o ClickHouseCommand
ExecuteNonQueryAsync()- Para instruções INSERT, UPDATE, DELETE e DDLExecuteScalarAsync()- Retorna a primeira coluna da primeira linhaExecuteReaderAsync()- Retorna umClickHouseDataReaderpara percorrer os resultados
Usando ClickHouseDataReader
ClickHouseDataReader fornece acesso tipado aos resultados da consulta:
Boas práticas
Ciclo de vida da conexão e pool de conexões
ClickHouse.Driver usa System.Net.Http.HttpClient internamente. O HttpClient tem um pool de conexões por endpoint. Como consequência:
- As sessões do banco de dados são multiplexadas por conexões HTTP gerenciadas pelo pool de conexões.
- As conexões HTTP são recicladas automaticamente pelo pool.
- As conexões podem permanecer ativas mesmo depois que os objetos
ClickHouseClientouClickHouseConnectionsão descartados.
Tratamento de DateTime
-
Use UTC sempre que possível. Armazene timestamps como colunas
DateTime('UTC')e useDateTimeKind.Utcno seu código. Isso elimina ambiguidades de fuso horário. -
Use
DateTimeOffsetpara lidar explicitamente com o fuso horário. Ele sempre representa um instante específico e inclui a informação de offset. -
Especifique o fuso horário nas type hints de SQL. Ao usar parâmetros com valores
DateTimeUnspecifieddestinados a colunas que não usam UTC, inclua o fuso horário no SQL:
Inserções assíncronas
CustomSettings ou pela connection string:
wait_for_async_insert):
Configurações principais:
Sessões
- Tabelas temporárias (
CREATE TEMPORARY TABLE) - Manter o contexto da consulta em várias instruções
- Configurações no nível da sessão (
SET max_threads = 4)
Tipos de dados compatíveis
ClickHouse.Driver é compatível com todos os tipos de dados do ClickHouse. As tabelas abaixo mostram o mapeamento entre os tipos do ClickHouse e os tipos nativos do .NET na leitura de dados do banco de dados.
Mapeamento de tipos: leitura do ClickHouse
Tipos inteiros
Tipos de ponto flutuante
Tipos decimais
A conversão de tipos decimais é controlada pela configuração UseCustomDecimals.
Tipo booleano
Tipos String
Por padrão, as colunas
String e FixedString(N) são retornadas como string. Defina ReadStringsAsByteArrays=true na string de conexão para lê-las como byte[]. Isso é útil ao armazenar dados binários que podem não estar em UTF-8 válido.Tipos de data e hora
O ClickHouse armazena internamente os valores
DateTime e DateTime64 como timestamps Unix (segundos ou frações de segundo desde a epoch). Embora o armazenamento seja sempre em UTC, as colunas podem ter um fuso horário associado, o que afeta como os valores são exibidos e interpretados.
Ao ler valores DateTime, a propriedade DateTime.Kind é definida com base no fuso horário da coluna:
Para colunas que não estão em UTC, o
DateTime retornado representa a hora local nesse fuso horário. Use ClickHouseDataReader.GetDateTimeOffset() para obter um DateTimeOffset com o deslocamento correto para esse fuso horário:
DateTime em vez de DateTime('Europe/Amsterdam')), o driver retorna um DateTime com Kind=Unspecified. Isso preserva exatamente a hora local como foi armazenada, sem fazer suposições sobre o fuso horário.
Se você precisar de um comportamento sensível a fuso horário para colunas sem fusos horários explícitos, faça uma destas opções:
- Use fusos horários explícitos nas definições das colunas:
DateTime('UTC')ouDateTime('Europe/Amsterdam') - Aplique o fuso horário manualmente após a leitura.
Tipo JSON
O tipo de retorno das colunas JSON é controlado pela configuração
JsonReadMode:
-
Binary(padrão): RetornaSystem.Text.Json.Nodes.JsonObject. Fornece acesso estruturado aos dados JSON, mas tipos especializados do ClickHouse (como endereços IP, UUIDs e valores decimais grandes) são convertidos para suas representações em string dentro da estrutura JSON. -
String: Retorna o JSON bruto comostring. Preserva a representação exata do JSON no ClickHouse, o que é útil quando você precisa repassar o JSON sem fazer o parsing ou quando deseja cuidar da desserialização por conta própria.
Outros tipos
Os tipos Dynamic e Variant serão convertidos para o tipo correspondente ao tipo subjacente real de cada linha.
Tipos de geometria
O tipo Geometry é um Variant que pode conter qualquer um dos tipos de geometria. Ele será convertido para o tipo correspondente.
Mapeamento de tipos: escrita no ClickHouse
Tipos inteiros
Tipos de ponto flutuante
Tipo booleano
Tipos String
Tipos de data e hora
O driver respeita
DateTime.Kind ao gravar valores:
Os valores de
DateTimeOffset sempre preservam o instante exato.
Exemplo: DateTime UTC (instante preservado)
DateTimeKind.Utc ou DateTimeOffset em todas as operações com DateTime. Isso garante que seu código funcione de forma consistente, independentemente do fuso horário do servidor, do cliente ou da coluna.
Parâmetros HTTP vs bulk copy
Unspecified de DateTime:
Bulk Copy conhece o fuso horário da coluna de destino e interpreta corretamente os valores Unspecified nesse fuso.
Parâmetros HTTP não conhecem automaticamente o fuso horário da coluna. Você deve especificá-lo na dica de tipo SQL:
Tipos Decimal
Tipo JSON
O comportamento ao escrever JSON é controlado pela configuração
JsonWriteMode:
-
String(padrão): Aceitastring,JsonObject,JsonNodeou qualquer objeto. Todas as entradas são serializadas comSystem.Text.Json.JsonSerializere enviadas como strings JSON para processamento no servidor. Este é o modo mais flexível e funciona sem registro de tipo. -
Binary: Aceita apenas tipos POCO registrados. Os dados são convertidos no cliente para o formato JSON binário do ClickHouse, com suporte completo a dicas de tipo. Requer chamarconnection.RegisterJsonSerializationType<T>()antes do uso. Escrever valoresstringouJsonNodenesse modo lançaArgumentException.
Colunas JSON tipadas
JSON(id UInt64, price Decimal128(2))), o driver usa essas dicas para serializar valores com total fidelidade aos tipos. Isso preserva a precisão de tipos como UInt64, Decimal, UUID e DateTime64, que, de outra forma, perderiam precisão ao serem serializados como JSON genérico.
Serialização de POCO
JsonWriteMode:
Modo String (padrão): os POCOs são serializados por meio de System.Text.Json.JsonSerializer. Não é necessário registrar tipos. Esta é a abordagem mais simples e funciona com objetos anônimos.
Modo binário: os POCOs são serializados usando o formato JSON binário do driver, com suporte completo a type hints. Os tipos devem ser registrados com connection.RegisterJsonSerializationType<T>() antes do uso. Esse modo oferece suporte a mapeamentos de path personalizados por meio de atributos:
-
[ClickHouseJsonPath("path")]: Mapeia uma propriedade para um path JSON personalizado. Útil para estruturas aninhadas ou quando o nome da propriedade difere da chave JSON desejada. Funciona apenas no modo binário. -
[ClickHouseJsonIgnore]: Exclui uma propriedade da serialização. Funciona apenas no modo binário.
UserId só corresponderá a uma dica definida como UserId, não como userid. Isso está de acordo com o comportamento do ClickHouse, que permite que caminhos como userName e UserName coexistam como campos separados.
Limitações (apenas no modo Binary):
- Os tipos POCO precisam ser registrados na conexão com
connection.RegisterJsonSerializationType<T>()antes da serialização. Tentar serializar um tipo não registrado lançaClickHouseJsonSerializationException. - Propriedades de Dicionário e array/lista exigem dicas de tipo na definição da coluna para serem serializadas corretamente. Sem essas dicas, use o modo String.
- Valores nulos em propriedades POCO só são gravados quando o caminho tem uma dica de tipo
Nullable(T)na definição da coluna. O ClickHouse não permite tiposNullableem caminhos JSON dinâmicos, portanto propriedades nulas sem dica são ignoradas. - Os atributos
ClickHouseJsonPatheClickHouseJsonIgnoresão ignorados no modo String (eles só funcionam no modo Binary).
Outros tipos
Tipos de geometria
Não suportado para escrita
Tratamento do tipo Nested
Nested(...)) podem ser lidos e gravados usando semântica de arrays.
Logging e diagnósticos
Microsoft.Extensions.Logging para oferecer logging leve e opcional. Quando habilitado, o driver emite mensagens estruturadas para eventos do ciclo de vida da conexão, execução de comandos, operações de transporte e operações de inserção em massa. O logging é totalmente opcional — aplicações que não configuram um logger continuam em execução sem sobrecarga adicional.
Início rápido
Usando appsettings.json
Usando configuração em memória
Categorias e emissores
Exemplo: Diagnóstico de problemas de conexão
- Seleção da fábrica do cliente HTTP (pool padrão vs. conexão única)
- Configuração do handler HTTP (SocketsHttpHandler ou HttpClientHandler)
- Configurações do pool de conexões (MaxConnectionsPerServer, PooledConnectionLifetime etc.)
- Configurações de timeout (ConnectTimeout, Expect100ContinueTimeout etc.)
- Configuração de SSL/TLS
- Eventos de abertura/fechamento de conexões
- Rastreamento do ID da sessão
Modo de depuração: rastreamento de rede e diagnósticos
ClickHouse.Driver.Diagnostic.TraceHelper). Os eventos serão registrados na categoria ClickHouse.Driver.NetTrace. Aviso: isso gerará logs extremamente detalhados e afetará o desempenho. Não é recomendável habilitar o modo de depuração em production.
OpenTelemetry
System.Diagnostics.Activity. Quando habilitado, o driver emite spans para operações de banco de dados que podem ser exportados para backends de observabilidade, como Jaeger ou o próprio ClickHouse (por meio do OpenTelemetry Collector).
Habilitando o rastreamento
ActivitySource do driver do ClickHouse à configuração do OpenTelemetry:
Atributos de span
Opções de configuração
ClickHouseDiagnosticsOptions:
Configuração de TLS
Validação personalizada de certificados
HttpClient com um handler ServerCertificateCustomValidationCallback configurado:
Considerações importantes ao fornecer um HttpClient personalizado
- Descompressão automática: Você deve habilitar
AutomaticDecompressionse a compressão não estiver desabilitada (a compressão é habilitada por padrão). - Tempo limite de inatividade: Defina
PooledConnectionIdleTimeoutcom um valor menor que okeep_alive_timeoutdo servidor (10 segundos para ClickHouse Cloud) para evitar erros de conexão causados por conexões semiabertas.
Suporte a ORMs
ClickHouseConnection). Para gerenciar corretamente o ciclo de vida da conexão, crie as conexões a partir de um ClickHouseDataSource:
Dapper
ClickHouse.Driver funciona com Dapper. O driver converte automaticamente a sintaxe @parameter do Dapper para a sintaxe nativa {parameter:Type} do ClickHouse, com os tipos inferidos a partir dos valores do .NET.
Use ClickHouseDataSource para gerenciar corretamente o ciclo de vida da conexão:
Estilos de passagem de parâmetros
DynamicParameters (a partir de um dicionário ou de um objeto anônimo):
Consultas com POCOs
Sintaxe nativa de parâmetros do ClickHouse
{param:Type} do ClickHouse com um Dictionary<string, object> para os valores dos parâmetros. Não combine a sintaxe @param com a sintaxe {param:Type} para o mesmo parâmetro.
WHERE IN
WHERE id IN (@Ids1, @Ids2, @Ids3), e o driver converte cada parâmetro expandido.
O has() do ClickHouse com parâmetro Array também funciona:
Manipuladores de tipo personalizados
ITuple, BigInteger e ClickHouseDecimal, precisam ter manipuladores registrados na inicialização:
Dapper.Contrib
GetAll<T>() e Get<T>(id) funcionam. Insert<T>() não — ele gera sintaxe do SQL Server (SCOPE_IDENTITY, []). Recomenda-se usar, em vez disso, o método nativo InsertBinaryAsync do ClickHouseClient.
Limitações
Linq2db
DataConnection usando o provedor do ClickHouse:
BulkCopyAsync para inserções em lote eficientes.
Entity Framework Core
SaveChanges — tudo usando os padrões familiares do EF Core.
- NuGet:
ClickHouse.EntityFrameworkCore - Código-fonte: GitHub
Este provedor está em desenvolvimento ativo. O lançamento atual oferece suporte a consultas LINQ (incluindo junções, subconsultas e operações de conjunto),
INSERT via SaveChanges / BulkInsertAsync, migrations com DDL completo (CREATE / ALTER / DROP) e configuração específica do motor de tabela do ClickHouse. UPDATE / DELETE não são suportados.Instalação
Início rápido
DbContext e, em seguida, consulte com LINQ:
Tipos com suporte
Use
ClickHouseDecimal (de ClickHouse.Driver.Numerics) em vez de decimal quando precisar da precisão total de colunas Decimal128/Decimal256 — o decimal do .NET é limitado a 28–29 dígitos significativos.
Operações LINQ compatíveis
Where, OrderBy, Take, Skip, Select, First, Single, Any, All, Count, Distinct, AsNoTracking
GROUP BY e agregações: GroupBy com Count, LongCount, Sum, Average, Min, Max — incluindo HAVING (.Where() após .GroupBy()), várias agregações em uma única projeção e OrderBy com base nos resultados agregados.
JOINs: Join (INNER), padrões GroupJoin/SelectMany (LEFT e CROSS). LEFT JOIN retorna null de fato para linhas sem correspondência (veja semântica de null em LEFT JOIN abaixo).
Subconsultas: Contains / IN correlacionados, Any / EXISTS, All e subconsultas escalares em projeções.
Operações de conjunto: Concat (→ UNION ALL), Union (→ UNION DISTINCT), Intersect, Except.
Coleções locais inline: junções e Contains em coleções em memória (int[], List<T>, etc.) são convertidos em uma série de UNIONs.
Métodos de string: Contains, StartsWith, EndsWith, IndexOf, Replace, Substring, Trim/TrimStart/TrimEnd, ToLower, ToUpper, Length, IsNullOrEmpty, Concat (e o operador +).
Funções matemáticas: métodos padrão de Math e MathF traduzidos para seus equivalentes no ClickHouse — funções aritméticas, logarítmicas, trigonométricas e utilitárias.
Semântica de NULL em LEFT JOIN
set_join_use_nulls=1 automaticamente em cada conexão para atender às expectativas do Entity Framework em relação ao comportamento de JOIN.
Se o seu servidor ClickHouse ou profile impedir a alteração dessa configuração (por exemplo, um profile readonly=1), desative isso com:
0 / "" em vez de == null.
Inserção de dados
SaveChanges usa a API nativa InsertBinaryAsync do driver — codificação RowBinary com compressão GZip, muito mais eficiente do que SQL parametrizado:
Added para Unchanged após salvar, assim como em qualquer outro provedor do EF Core.
O tamanho do lote é configurável (padrão: 1000):
Inserção em massa
BulkInsertAsync em vez de SaveChanges. Esse é um método de extensão no DbContext que ignora completamente o rastreador de alterações, a resolução de identidade e o gerenciamento de estado do EF Core — ele chama diretamente o InsertBinaryAsync do driver com codificação RowBinary e compressão GZip.
Isso o torna ideal para carregar grandes conjuntos de dados quando você não precisa rastrear entidades após a inserção:
IEnumerable<T> — ela processa as entidades em fluxo, sem carregá-las todas na memória. O valor retornado é o número de linhas inseridas. As entidades não ficam vinculadas ao DbContext após a inserção, portanto não há transição de estado de Added → Unchanged.
Enums
Enum8/Enum16 do ClickHouse podem ser mapeadas como propriedades string ou como tipos enum em C#. Ao usar enums em C#, o provedor converte automaticamente entre o enum e sua representação textual:
Conversões de tipos personalizadas
ValueConverter do EF Core permite mapear tipos personalizados para tipos que o provedor já suporta. O provedor nunca vê seu tipo personalizado — o EF Core faz a conversão na interface entre os dois.
Conversão por propriedade:
Anotações de tipo de coluna
string, int, DateTime etc., o provedor deduz automaticamente o tipo do ClickHouse. Para tipos parametrizados e wrappers, é necessário especificar explicitamente o tipo do ClickHouse.
Usando anotações de dados (atributos):
OnModelCreating:
Array(Nullable(Int32)) e LowCardinality(Nullable(String)) são suportados — o provedor desempacota Nullable e LowCardinality automaticamente em todos os níveis de aninhamento.
Colunas Variant e Dynamic
Variant(T1, T2, ...) e Dynamic do ClickHouse são mapeadas para object no .NET. Como object é genérico demais para a inferência automática de tipos, você deve declarar explicitamente o tipo de armazenamento por meio de .HasColumnType():
string, ulong, ulong[]).
Colunas JSON
Json do ClickHouse, com mapeamento para System.Text.Json.Nodes.JsonNode (principal) ou string (via ValueConverter automático):
SaveChanges quanto com BulkInsertAsync:
string, com o tipo de coluna Json — o provedor aplica um ValueConverter automaticamente:
- Sem tradução de caminhos JSON —
entity.Data["name"]no LINQ não é convertido para a sintaxe SQLdata.namedo ClickHouse. Filtre colunas não JSON e inspecione o JSON na memória. - Semântica de NULL — o tipo JSON do ClickHouse retorna
{}(objeto vazio) para valores NULL, em vez de SQL NULL. - Precisão de inteiros — o JSON do ClickHouse armazena todos os inteiros como
Int64. Ao ler comJsonNode, useGetValue<long>()em vez deGetValue<int>().
Motores de tabela
ToTable(name, t => ...). Quando nenhum motor é configurado, o provedor usa MergeTree, com ORDER BY derivado da chave primária da entidade.
Cláusulas do motor:
WithOrderBy, WithPartitionBy, WithPrimaryKey, WithSampleBy, WithTtl, WithSettings. Todas são anexadas ao construtor de motor retornado por HasXxxEngine().
Recursos em nível de coluna: HasCodec, HasTtl, HasComment, HasDefault — todos participam das migrações.
Índices de data skipping — via HasIndex(...).HasSkippingIndexType(...):
Migrações
Limitações de migração
Além das migrações, o provedor também ainda não oferece suporte a:
UPDATE/DELETE- Transações:
BeginTransactioné um no-op. Não há suporte a transações ACID no ClickHouse. - Tradução de consultas com caminho JSON:
entity.Data["key"]em LINQ não é traduzido para a sintaxe SQLdata.keydo ClickHouse. Aplique filtros em colunas não JSON e inspecione o JSON na memória.
Limitações
Colunas do tipo AggregateFunction
AggregateFunction(...) não podem ser consultadas nem inseridas diretamente.
Para inserir: