-
ClickHouseClient(推荐) :一个高级、线程安全的客户端,适合以单例方式使用。为查询和批量插入提供简洁的异步 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
安装
快速入门
配置
- **连接字符串:**由分号分隔的键/值对,用于指定主机、身份验证凭据和其他连接选项。
- **
ClickHouseClientSettingsobject:**强类型配置对象,可从配置文件中加载,也可在代码中设置。
连接设置
数据格式与序列化
会话管理
UseSession 标志会启用服务器会话持久化,从而可以使用 SET 语句和临时表。会话在 60 秒无活动后会被重置 (默认超时) 。可通过 ClickHouse 语句或服务器配置中的会话设置来延长会话生命周期。ClickHouseConnection 类通常支持并行操作 (多个线程可并发运行查询) 。但启用 UseSession 标志后,任意时刻每个连接只允许有一个活动查询 (这是服务器端限制) 。安全
HTTP 客户端配置
日志与调试
自定义设置与角色
使用连接字符串设置自定义设置时,请使用
set_ 前缀,例如 set_max_threads=4。使用 ClickHouseClientSettings 对象时,不要使用 set_ 前缀。有关可用设置的完整列表,请参见此处。连接字符串示例
基本连接
使用自定义 ClickHouse 设置
QueryOptions
QueryOptions 允许你按查询覆盖客户端级别的设置。所有属性均为可选,只有在指定时才会覆盖客户端默认值。
示例:
InsertOptions
InsertOptions 在 QueryOptions 的基础上增加了通过 InsertBinaryAsync 执行批量插入操作所需的特定设置。
QueryOptions 的所有属性也可用于 InsertOptions。
示例:
跳过 schema 探测查询
InsertBinaryAsync 会在每次 insert 之前发送一个 SELECT ... WHERE 1=0 查询,以探测列类型。对于高吞吐量场景,你可以通过以下两种方式消除这部分开销:
选项 1:显式提供列类型
当你在编译时就已知表的 schema 时,可通过 ColumnTypes 直接传入。这样就完全不会发送 schema 查询:
UseSchemaCache = true,这样只需查询一次 schema,后续在同一个 ClickHouseClient 实例上插入时即可复用:
ColumnTypes的优先级高于UseSchemaCache。如果两者都已设置,则使用显式指定的类型。- schema 缓存无法检测
ALTER TABLE带来的变更。如果你修改了表的 schema,请创建新的ClickHouseClient,或避免对该表使用UseSchemaCache。 - 缓存的作用域仅限于
ClickHouseClient实例,并以 (database,table) 为键。同一张表的不同列子集会共享同一个缓存的 schema。
ClickHouseClient
ClickHouseClient 是与 ClickHouse 交互时推荐使用的 API。它是线程安全的,采用单例模式设计,并在内部管理 HTTP 连接池。
创建客户端
ClickHouseClientSettings 对象创建 ClickHouseClient。可用选项请参阅配置部分。
你的 ClickHouse Cloud 服务的详细信息可在 ClickHouse Cloud 控制台中查看。
选择一个服务并点击 Connect:
选择 C#。连接详细信息会显示在下方。
如果你使用的是自管理 ClickHouse,连接详细信息由你的 ClickHouse 管理员提供。
使用连接字符串:
ClickHouseClientSettings:
IHttpClientFactory:
ClickHouseClient 设计为可长期使用,并可在整个应用程序中共享。只需创建一次 (通常作为单例) ,并在所有数据库操作中重复使用。该客户端会在内部管理 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。 - 如果你希望服务器为未提供的列应用 DEFAULT 值,请在
InsertOptions.Format中使用RowBinaryFormat.RowBinaryWithDefaults。
POCO 插入
object[] 数组,可直接插入强类型的 POCO 对象。只需注册一次该类型,然后传入 IEnumerable<T>:
当所有映射属性都显式指定了
Type 时,会完全跳过 schema 探测查询。只有部分属性显式指定类型时,驱动程序会回退为对完整列集执行 schema 探测查询。
InsertBinaryAsync<T> 支持与 object[] 重载相同的 InsertOptions (批处理、并行度、schema 缓存) 。
与
object[] 重载不同,InsertBinaryAsync<T> 不接受显式列列表。列由已注册类型的映射属性决定。要控制插入哪些列,可使用 [ClickHouseNotMapped] 排除属性,或使用 [ClickHouseColumn(Name = "...")] 为属性重命名。如果在 InsertOptions 中设置了 ColumnTypes,它们会覆盖 POCO 特性。schema 演进
DEFAULT (或其他默认表达式) 的新列都会由 server 自动补齐。无需修改代码,也无需重新注册。
读取数据
ExecuteReaderAsync 执行 SELECT 查询。返回的 ClickHouseDataReader 可通过 GetInt64()、GetString() 和 GetFieldValue<T>() 等方法,以强类型方式访问结果列。
调用 Read() 以移动到下一行。没有更多行时,它会返回 false。可以按索引 (从 0 开始) 或列名访问列。
SQL 参数
{parameter_name:DataType}。
示例:
SQL ‘绑定’参数通过 HTTP URI 查询参数传递,因此如果使用过多,可能会导致出现 “URL 过长” 异常。为避免这一限制,在批量插入数据时请使用
InsertBinaryAsync。查询 ID
query_id,可用于从 system.query_log 表中查询数据,或取消长时间运行的查询。你可以通过 QueryOptions 指定自定义的查询 ID:
自定义参数类型映射
@ 风格的参数时 (例如 WHERE id = @id) ,驱动程序会根据 .NET 值类型自动推断 ClickHouse 类型。例如,int 会映射为 Int32,DateTime 会映射为 DateTime。
如需覆盖这些默认映射,请在 ClickHouseClientSettings 上设置 ParameterTypeResolver。例如,如果你希望所有 DateTime 参数都使用具有毫秒精度的 DateTime64(3),或者希望所有 Decimal 参数都使用特定的标度,而不必为每个参数单独设置 ClickHouseType,这会很有用。
使用 DictionaryParameterTypeResolver 进行简单的类型映射:
IParameterTypeResolver:
对于按值或按名称进行解析的场景,请直接实现 IParameterTypeResolver 接口。返回 null 以回退到默认推断:
QueryOptions.ParameterTypeResolver 为单个查询设置解析器。设置后,它会优先于客户端级别的解析器。
类型解析优先级:
解析器只是这一优先级事件链中的一环。按优先级从高到低依次为:
- 在参数上显式设置的
ClickHouseType - 查询中通过
{name:Type}语法指定的 SQL 类型提示 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 提供完整的 ADO.NET 支持。ORM 集成 (Dapper、Linq2db) 以及需要标准 .NET 数据库抽象时,都必须使用此 API。
使用 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 类型提示中指定时区。 当参数中使用
Unspecified的 DateTime 值,且目标列不是 UTC 时,请在 SQL 中包含时区信息:
异步插入
CustomSettings 或连接字符串启用异步插入:
wait_for_async_insert 控制) :
关键设置:
会话
- 临时表 (
CREATE TEMPORARY TABLE) - 在多条语句之间保持查询上下文
- 会话级设置 (
SET max_threads = 4)
支持的数据类型
ClickHouse.Driver 支持所有 ClickHouse 数据类型。下表展示了从数据库读取数据时,ClickHouse 类型与原生 .NET 类型之间的映射。
类型映射:从 ClickHouse 读取
整型
浮点类型
Decimal 类型
Decimal 类型的转换由 UseCustomDecimals 设置控制。
布尔类型
String 类型
默认情况下,
String 和 FixedString(N) 列都会作为 string 返回。要将它们改为读取为 byte[],请在连接字符串中设置 ReadStringsAsByteArrays=true。这在存储可能不是有效 UTF-8 的二进制数据时非常有用。日期和时间类型
ClickHouse 在内部将
DateTime 和 DateTime64 值存储为 Unix 时间戳 (即自纪元以来的秒或亚秒单位) 。虽然存储始终采用 UTC,但列可以关联一个时区,这会影响值的显示和解析方式。
读取 DateTime 值时,DateTime.Kind 属性会根据列的时区进行设置:
对于非 UTC 列,返回的
DateTime 表示该时区中的挂钟时间。使用 ClickHouseDataReader.GetDateTimeOffset() 可获取带有该时区正确偏移量的 DateTimeOffset:
DateTime,而不是 DateTime('Europe/Amsterdam')) ,驱动程序 会返回一个 Kind=Unspecified 的 DateTime。这样可以原样保留存储的挂钟时间,而不对时区作任何假定。
如果你需要让没有显式时区的列具备时区感知行为,可以:
- 在列定义中显式指定时区:
DateTime('UTC')或DateTime('Europe/Amsterdam') - 读取后自行应用时区。
JSON 类型
JSON 列的返回类型由
JsonReadMode 设置控制:
-
Binary(默认) :返回System.Text.Json.Nodes.JsonObject。可对 JSON 数据进行结构化访问,但专用的 ClickHouse 类型 (如 IP 地址、UUID、较大精度的 Decimal) 会在 JSON 结构中转换为字符串表示形式。 -
String:以string形式返回原始 JSON。保留 ClickHouse 中 JSON 的精确表示形式,这在你需要不经解析直接传递 JSON,或想自行处理反序列化时非常有用。
其他类型
Dynamic 和 Variant 类型会转换为每一行实际底层类型对应的类型。
几何类型
Geometry 类型是一种 Variant 类型,可容纳任意几何类型。它会被转换为对应的类型。
类型映射:写入 ClickHouse
整数类型
浮点类型
布尔类型
String 类型
日期和时间类型
驱动在写入值时会遵循
DateTime.Kind:
DateTimeOffset 值始终保留精确时刻。
示例:UTC DateTime (保留精确时刻)
DateTimeKind.Utc 或 DateTimeOffset。这样可以确保你的代码始终保持一致,不受服务器时区、客户端时区或列时区的影响。
HTTP 参数与批量复制
Unspecified DateTime 值时,HTTP 参数绑定和批量复制之间有一个重要区别:
批量复制 知道目标列的时区,因此会按该时区正确解释 Unspecified 值。
HTTP 参数 不会自动获知列的时区。你必须在 SQL 类型提示中显式指定它:
Decimal 类型
JSON 类型
写入 JSON 时的行为由
JsonWriteMode 设置控制:
-
String(默认) :接受string、JsonObject、JsonNode或任意对象。所有输入都会通过System.Text.Json.JsonSerializer序列化,并作为 JSON 字符串发送到服务端解析。这是最灵活的模式,无需注册类型即可使用。 -
Binary:仅接受已注册的 POCO 类型。数据会在客户端转换为 ClickHouse 的二进制 JSON 格式,并完整支持类型提示。使用前需要调用connection.RegisterJsonSerializationType<T>()。在此模式下写入string或JsonNode值会抛出ArgumentException。
带类型提示的 JSON 列
JSON(id UInt64, price Decimal128(2))) 时,驱动程序会利用这些提示对值进行序列化,从而完整保留类型信息。这样可以保留 UInt64、Decimal、UUID 和 DateTime64 等类型的精度,否则它们在按通用 JSON 序列化时可能会损失精度。
POCO 序列化
JsonWriteMode,可通过两种方式将 POCO 写入 JSON 列:
String 模式 (默认) :POCO 通过 System.Text.Json.JsonSerializer 进行序列化。无需注册类型。这是最简单的方法,也适用于匿名对象。
Binary 模式:POCO 使用驱动的二进制 JSON 格式进行序列化,并完整支持 类型提示。使用前必须通过 connection.RegisterJsonSerializationType<T>() 注册类型。此模式还支持通过特性自定义 path 映射:
-
[ClickHouseJsonPath("path")]:将属性映射到自定义 JSON path。适用于嵌套结构,或属性名与所需的 JSON 键不一致时。仅在 Binary 模式下有效。 -
[ClickHouseJsonIgnore]:序列化时排除此属性。仅在 Binary 模式下有效。
UserId 只会匹配定义为 UserId 的提示,不会匹配 userid。这与 ClickHouse 的行为一致:它允许 userName 和 UserName 作为两个不同的字段并存。
限制 (仅 Binary 模式) :
- 在序列化之前,必须通过
connection.RegisterJsonSerializationType<T>()在 connection 上注册 POCO 类型。尝试序列化未注册的类型会抛出ClickHouseJsonSerializationException。 - 字典以及数组/列表属性需要在列定义中提供类型提示,才能正确序列化。没有提示时,请改用 String 模式。
- 只有当该 path 在列定义中具有
Nullable(T)类型提示时,POCO 属性中的 NULL 值才会被写入。ClickHouse 不允许在动态 JSON path 中使用Nullable类型,因此未提供提示的 null 属性会被跳过。 - 在 String 模式下,
ClickHouseJsonPath和ClickHouseJsonIgnore特性会被忽略 (它们仅在 Binary 模式下生效) 。
其他类型
几何类型
不支持写入的类型
嵌套类型处理
Nested(...)) 可按数组语义进行读写。
日志与诊断
Microsoft.Extensions.Logging 抽象,提供轻量、按需启用的日志功能。启用后,驱动程序会针对连接生命周期事件、命令执行、传输操作以及批量插入操作输出结构化消息。日志功能完全是可选的——未配置日志记录器的应用程序仍可继续运行,且不会带来额外开销。
快速入门
使用 appsettings.json
使用内存中的配置
类别和发出方
示例:排查连接问题
- HTTP 客户端工厂的选择 (默认连接池或单个连接)
- HTTP handler 配置 (SocketsHttpHandler 或 HttpClientHandler)
- 连接池设置 (MaxConnectionsPerServer、PooledConnectionLifetime 等)
- 超时设置 (ConnectTimeout、Expect100ContinueTimeout 等)
- SSL/TLS 配置
- 连接打开/关闭事件
- 会话 ID 跟踪
调试模式:网络跟踪与诊断
ClickHouse.Driver.Diagnostic.TraceHelper 类手动启用) 。事件会记录到 ClickHouse.Driver.NetTrace 类别中。警告:这会生成极其详细的日志,并影响性能。不建议在生产环境中启用调试模式。
OpenTelemetry
System.Diagnostics.Activity API 实现的 OpenTelemetry 分布式链路追踪的支持。启用后,驱动程序会为数据库操作生成 span,并可将其导出到 Jaeger 或 ClickHouse 自身等可观测性后端 (通过 OpenTelemetry Collector) 。
启用链路追踪
ActivitySource 添加到 OpenTelemetry 配置中:
Span 属性
配置选项
ClickHouseDiagnosticsOptions 控制链路追踪行为:
TLS 配置
自定义证书验证
HttpClient,并配置 ServerCertificateCustomValidationCallback 处理程序:
使用自定义 HttpClient 时的重要注意事项
- 自动解压缩:如果未禁用压缩,则必须启用
AutomaticDecompression(压缩默认处于启用状态) 。 - 空闲超时:将
PooledConnectionIdleTimeout设置为小于服务器的keep_alive_timeout(ClickHouse Cloud 中为 10 秒) ,以避免半开连接导致的连接错误。
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),驱动程序随后会转换每个展开后的参数。
ClickHouse 的 has() 也支持配合 Array 参数使用:
自定义类型处理器
ITuple、BigInteger 和 ClickHouseDecimal) 需要在启动时注册相应的处理器:
Dapper.Contrib
GetAll<T>() 和 Get<T>(id) 可以正常工作。Insert<T>() 不支持——它会生成 SQL Server 语法 (SCOPE_IDENTITY、[]) 。建议改用 ClickHouseClient 原生的 InsertBinaryAsync 方法。
局限性
Linq2db
DataConnection:
BulkCopyAsync 可高效执行批量插入。
Entity Framework Core
SaveChanges 插入数据——全部采用熟悉的 EF Core 模式。
- NuGet:
ClickHouse.EntityFrameworkCore - Source: GitHub
该提供商仍在积极开发中。当前版本支持 LINQ 查询 (包括 JOIN、子查询和集合运算) 、通过
SaveChanges / BulkInsertAsync 执行 INSERT、支持完整 DDL (CREATE / ALTER / DROP) 的迁移,以及 ClickHouse 特有的表引擎配置。不支持 UPDATE / DELETE。安装
快速入门
DbContext,然后使用 LINQ 查询:
支持的类型
在需要
Decimal128/Decimal256 列的完整精度时,请使用 ClickHouseDecimal (来自 ClickHouse.Driver.Numerics) ,而不是 decimal——.NET 的 decimal 仅支持 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 (在 .GroupBy() 之后调用 .Where()) 、在单个投影中使用多个聚合,以及按聚合结果执行 OrderBy。
JOIN: Join (INNER) 、GroupJoin/SelectMany 模式 (LEFT 和 CROSS) 。对于不匹配的行,LEFT JOIN 会返回实际的 null (参见下方的 LEFT JOIN null 语义) 。
子查询: 关联 Contains / IN、Any / EXISTS、All,以及投影中的标量子查询。
集合操作: Concat (→ UNION ALL) 、Union (→ UNION DISTINCT) 、Intersect、Except。
内联本地集合: 针对内存中集合 (int[]、List<T> 等) 的联接和 Contains 会被转换为一系列 UNION。
字符串方法: Contains, StartsWith, EndsWith, IndexOf, Replace, Substring, Trim/TrimStart/TrimEnd, ToLower, ToUpper, Length, IsNullOrEmpty, Concat (以及 + 运算符) 。
数学函数: 标准 Math 和 MathF 方法会被转换为对应的 ClickHouse 函数 —— 包括算术、对数、三角和实用函数。
LEFT JOIN 的 NULL 语义
set_join_use_nulls=1,以使 JOIN 行为符合 Entity Framework 的预期。
如果你的 ClickHouse 服务器或 profile 禁止更改此设置 (例如 readonly=1 profile) ,可通过以下方式禁用:
0 / "" 比较,不要使用 == null。
插入数据
SaveChanges 使用驱动程序提供的原生 InsertBinaryAsync API——采用 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 会在边界处完成转换。
针对单个属性的转换:
列类型注解
string、int、DateTime 等标量类型,提供商会自动推断出 ClickHouse 类型。对于参数化类型和包装类型,则需要显式指定 ClickHouse 类型。
使用数据注解 (attribute) :
OnModelCreating 中使用 Fluent API:
Array(Nullable(Int32)) 和 LowCardinality(Nullable(String)) 这类嵌套包装类型——提供程序会在每一层嵌套中自动解开 Nullable 和 LowCardinality。
Variant 和 Dynamic 列
Variant(T1, T2, ...) 和 Dynamic 列在 .NET 中会映射为 object。由于 object 过于宽泛,无法自动推断类型,因此必须通过 .HasColumnType() 显式声明存储类型:
string、ulong、ulong[]) 。
JSON 列
Json 列类型,可映射到 System.Text.Json.Nodes.JsonNode (主要) 或 string (通过自动 ValueConverter) :
SaveChanges,也可通过 BulkInsertAsync 完成:
string,并将列类型设为 Json——提供程序会自动应用 ValueConverter:
- 不支持 JSON 路径转换 — LINQ 中的
entity.Data["name"]不会转换为 ClickHouse 的data.nameSQL 语法。请对非 JSON 列进行过滤,并在内存中检查 JSON 内容。 - NULL 语义 — 对于 NULL 值,ClickHouse 的 JSON 类型返回的是
{}(空对象) ,而不是 SQL NULL。 - 整数精度 — ClickHouse JSON 会将所有整数存储为
Int64。通过JsonNode读取时,应使用GetValue<long>(),而不是GetValue<int>()。
表引擎
ToTable(name, t => ...) 流式 API 配置 ClickHouse 表引擎及引擎特定子句。若未配置引擎,提供商默认使用 MergeTree,并根据实体的主键确定 ORDER BY。
引擎子句:
WithOrderBy, WithPartitionBy, WithPrimaryKey, WithSampleBy, WithTtl, WithSettings。它们都会附加到 HasXxxEngine() 返回的引擎构建器上。
列级功能: HasCodec, HasTtl, HasComment, HasDefault —— 都会纳入迁移。
数据跳过索引 —— 通过 HasIndex(...).HasSkippingIndexType(...):
迁移
迁移限制
除迁移外,该提供商目前还不支持:
UPDATE/DELETE- 事务:
BeginTransaction是空操作。ClickHouse 不支持 ACID 事务。 - JSON 路径查询转换:LINQ 中的
entity.Data["key"]不会转换为 ClickHouse 的data.keySQL 语法。请对非 JSON 列进行过滤,并在内存中检查 JSON。
局限性
AggregateFunction 列
AggregateFunction(...) 类型的列。
如需插入: