delta lake 在 c# 中无原生支持,唯一可靠方案是通过 microsoft.spark 启动 jvm 子进程调用 spark sql;需配置 delta 扩展、使用分布式路径,并避免手动解析日志。

Delta Lake 在 C# 中没有原生支持
Delta Lake 是基于 Apache Spark 构建的存储层,核心实现(如事务日志、版本控制、ACID 语义)全部绑定在 JVM 生态里。C# 没有官方 SDK,也没有 Microsoft.Data.Delta 这类 NuGet 包。直接用 System.IO 读写 _delta_log 目录或 Parquet 文件,只会拿到原始字节或损坏的元数据——Delta 表不是“一堆 Parquet 文件 + 一个文件夹”那么简单。
必须通过 Spark .NET(Microsoft.Spark)桥接
目前唯一可靠路径是用 Microsoft.Spark 在 .NET 进程中启动 JVM 子进程,调用 Spark SQL 操作 Delta 表。这不是纯托管方案,但能复用 Spark 的完整 Delta 引擎。
- 需安装 Java 11+ 和 Spark 3.3+(Delta Lake 2.4+ 要求 Spark 3.3+)
- 项目引用
Microsoft.SparkNuGet 包(注意版本匹配:Spark 3.3.x 对应Microsoft.Spark/3.3.0) -
spark-submit不可用;必须用dotnet spark-submit启动(由Microsoft.Spark.Worker提供) - Delta 表路径必须是分布式存储路径(
abfss://,s3a://,file:///),本地相对路径./delta-table会失败
示例:读取表
var spark = SparkSession.Builder()
.AppName("DeltaReader")
.Config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension")
.Config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog")
.GetOrCreate();
<p>var df = spark.Read().Format("delta").Load("abfss://container@account.dfs.core.windows.net/delta-table");写入 Delta 表时必须显式启用 Delta 支持
Spark .NET 默认不加载 Delta 插件。漏掉 spark.sql.extensions 或 spark.sql.catalog 配置,会导致 SaveAsTable 报错 ClassNotFoundException: io.delta.sql.DeltaSparkSessionExtension,或写成普通 Parquet 而非 Delta 表。
- 写入前务必确认 SparkSession 已配置 Delta 扩展(见上一节代码)
- 使用
DataFrameWriter.Format("delta"),不能用"parquet"或省略格式 - 追加写入用
Mode("append"),覆盖写入用Mode("overwrite");Delta 不支持"ignore"模式 - 如果目标路径已存在非 Delta 数据,
overwrite会清空整个目录并重建_delta_log,不是原子替换
无法绕过 JVM 做轻量级 Delta 操作
有人尝试用 ParquetSharp 读 part-*.parquet、用 Newtonsoft.Json 解析 _delta_log/00000000000000000000.json,这条路走不通。Delta 日志不是简单 JSON 列表:add / remove 条目含 base64 编码的统计信息、时间戳精度为纳秒、checksum 校验跨多文件、并发写入依赖 _last_checkpoint 文件协调。手写解析极易漏掉 protocol 版本升级、metadata 变更等隐式约束。
真正需要低延迟、无 Spark 的场景(比如配置表热更新),建议换用 Parquet + 单文件 JSON 元数据,而不是硬套 Delta Lake。










