Databases and Data Access

Dapper (+ Dapper.FSharp) Micro-ORM: SQL with object mapping; Dapper.FSharp adds a CE-based query DSL Functional ADO.NET wrapper

Type-safe query builders generated from your schema Type provider for many databases Compile-time checked SQL for SQL Server

Entity Framework Core (+ EFCore.FSharp) PostgreSQL-friendly functional API PostgreSQL document DB and event store

LiteDB, MongoDB.Driver, StackExchange.Redis DbUp, Evolve, Grate

// Dapper (micro-ORM) with records
#r "nuget: Dapper"
#r "nuget: Microsoft.Data.Sqlite"
open Dapper
open Microsoft.Data.Sqlite

[<CLIMutable>]
type User = { Id: int64; Name: string; Email: string }

let connStr = "Data Source=app.db"
let createTable () =
    use conn = new SqliteConnection(connStr)
    conn.Execute("CREATE TABLE IF NOT EXISTS Users (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT)") |> ignore

let insertUser (name: string) (email: string) =
    use conn = new SqliteConnection(connStr)
    conn.Execute("INSERT INTO Users (Name, Email) VALUES (@Name, @Email)", {| Name = name; Email = email |})   // parameterized

let getUsers () =
    use conn = new SqliteConnection(connStr)
    conn.Query<User>("SELECT Id, Name, Email FROM Users WHERE Name LIKE @Pattern", {| Pattern = "A%" |}) |> List.ofSeq

let getUserAsync (id: int64) = task {
    use conn = new SqliteConnection(connStr)
    let! users = conn.QueryAsync<User>("SELECT * FROM Users WHERE Id = @Id", {| Id = id |})
    return Seq.tryHead users
}