Typed SQL for F# with no mapping code. Write SQL, get F# records back; hand it F# records and it inserts them. fss works with DuckDB, PostgreSQL and SQLite.
open Fss.Data.DuckDB
type Sale = { region : string ; product : string ; revenue : decimal }
use db = new DynamicSqlConnection("Data Source=:memory:")
// Query a Parquet file (or CSV, JSON, or a table) straight into records
let top =
db.Query<Sale>("""
select region, product, sum(qty * price) as revenue
from 'sales/*.parquet'
where region = $region
group by all order by revenue desc limit 10""", [ "region", box "west" ])
|> List.ofSeq| Package | Database | Driver | Status |
|---|---|---|---|
fss_duckdb |
DuckDB (in-process analytics) | DuckDB.NET | Primary. |
fss_postgres |
PostgreSQL | Npgsql | Maintained |
fss_sqlite |
SQLite | Microsoft.Data.Sqlite | Maintained |
fss_mysql |
MySQL | MySql.Data | Retired (no new releases) |
fss |
— | — | Legacy HTTP server and Jinja-style templates |
The database packages are independent of each other and of fss. Reference only the one you need:
dotnet add package fss_duckdbAll packages target .NET 10.
- Query to records:
db.Query<'T>(sql)maps columns to record fields by name (case-insensitive).optionfields take NULLs. It also maps to tuples (columns by position) and to single values (Query<int64> "select count(*) ..."). - Insert records:
db.InsertOne(record)anddb.InsertMany(records)build theINSERTfrom the table's metadata and return the generated primary keys. - Parameters: pass
[ "name", box value ]toQuery,ExecuteScalarandExecuteNonQuery. Never splice user input into SQL. - Transactions:
use t = db.StartTrans()exposes the same API. Callt.Commit()to commit; disposing without committing rolls back. - Type conversion: handles the usual driver mismatches, such as SQLite's
int64→int/bool, DuckDB'sHUGEINT→int64,DATE→DateOnly, text → F# enum, anduuid→Guid. - Pooling: each
DynamicSqlConnectionowns a small pool of connections and is safe to share between threads.
- Getting started: the core concepts, for every database
- DuckDB guide: files, in-memory databases, types and bulk loading
- PostgreSQL guide: schemas, enums, search path and keep-alive
- SQLite guide
- API reference
- Legacy: web server · templates · MySQL
- Release notes
Runnable projects live in samples/. The DuckDB samples are a good place to start:
dotnet run --project samples/DuckDbQuickStart
dotnet run --project samples/DuckDbAnalyticsYou need the .NET 10 SDK.
dotnet build fss.slnx
dotnet test fss.slnx # DuckDB + SQLite tests always run
FSS_TEST_POSTGRES="Host=localhost;Username=postgres;Password=...;Database=fsstest" dotnet test fss.slnxPostgres and MySQL tests are skipped unless FSS_TEST_POSTGRES / FSS_TEST_MYSQL are set. Contributors and
maintainers should read MAINTAINERS.md.
Apache 2.0. See LICENSE.