Write familiar LINQ, get analytical SQL
Joins, grouping, ordering, aggregates, string, math, temporal, arrays, JSON traversal, and relational composition — all translated for DuckDB.
Write LINQ, SaveChanges, and migrations on EF Core 10 — while your data tiers from a hot DuckDB file out to hive-partitioned Parquet on S3, GCS, or Azure, or lives in a shared DuckLake catalog. One analytical read model, from laptop to cloud.
This is the provider LakeHold itself runs on. Everything documented here is exercised by a product in production, not only by its own test suite.
Not an adapter or a query-only shim — a complete relational provider that speaks both fluent EF Core and analytical DuckDB.
Joins, grouping, ordering, aggregates, string, math, temporal, arrays, JSON traversal, and relational composition — all translated for DuckDB.
Appender-backed BulkInsert reaches roughly one million rows per second, and primary-key Upsert stages an appender batch into a set-based merge.
Map entities directly onto Parquet, CSV, or JSON — local or on object storage. Keep the data where it is and compose over it with LINQ.
SaveChanges, transactions, migrations, optimistic concurrency, scaffolding, and store-generated keys, on the native DuckDB profile.
Capture exact SQL and parameters for queries and terminal aggregates, replay named commands unchanged, and inspect store-type support through public APIs.
Start embedded, add a Parquet archive tier when history outgrows the file, or join a shared DuckLake catalog. Same package, same LINQ.
A complete relational provider over a local file: tracking, transactions, migrations, scaffolding, and analytical LINQ.
options.UseDuckDB("Data Source=app.duckdb")Keep the working set hot and writable; archive complete relational aggregates to hive-partitioned Parquet on disk or object storage.
modelBuilder.ToTieredStore<Record>(…)Tracked writes, commit metadata, named-secret shares, and independent read-only contexts against a shared catalog. This is the profile LakeHold uses.
options.UseDuckLake("catalog/analytics.ducklake")Archive whole relational aggregates — roots and their children together — to hive-partitioned Parquet, and keep reporting across the full history with ordinary LINQ.
Recent entities, relationships, SaveChanges, and Include.
Named Hive partitions on disk, S3, GCS, R2, or Azure object storage.
Generated union views keep both tiers behind one LINQ read model. Ordinary property filters become partition predicates, so DuckDB opens only matching files — verified with DuckDB EXPLAIN file counts in the release suite.
Keep tracked, transactional writes when semantics matter. Switch to the appender-backed path when throughput does.
Measured on a developer laptop; run the included BenchmarkDotNet project on your own hardware. BulkInsert bypasses change tracking and store-generated values — use it when raw ingestion speed is the goal.
DuckDB is an embedded, single-writer analytical engine. It is not a drop-in system of record for high-concurrency, multi-instance transactional workloads.
Backends and connection options, LINQ translation, non-executing command plans, write paths, file analytics, DuckLake, tiered storage, diagnostics, and the compatibility boundary.