Skip to content

Instantly share code, notes, and snippets.

@michaeloyer
Created February 16, 2022 13:51
Show Gist options
  • Save michaeloyer/3aa6e8e608114712c767a318208447ab to your computer and use it in GitHub Desktop.
Save michaeloyer/3aa6e8e608114712c767a318208447ab to your computer and use it in GitHub Desktop.
Demonstrating how to use a database with F#. Run this with `dotnet fsi script.fsx`
#r "nuget: System.Data.SQLite"
#r "nuget: Dapper"
open System
open Dapper
open System.Data
open System.Data.SQLite
[<CLIMutable>] // This creates private setters for Dapper to work with, but your F# code cannot
type Person = { Id: int; First: string; Last: string }
// Example of Regular Class (Non Record class like above)
// type Person() =
// member val Id = 0 with get, set
// member val First = "" with get, set
// member val Last = "" with get, set
// override this.ToString() = $"ID = {this.Id}; First = {this.First}; Last = {this.Last}"
type IPersonRepo =
abstract GetPeople: unit -> Person seq
abstract AddPerson: first:string * last:string -> int
type PersonRepo(cn: IDbConnection) =
interface IPersonRepo with
member _.GetPeople() =
cn.Query<Person>("SELECT Id, First, Last FROM People")
member _.AddPerson(first: string, last:string) =
cn.Execute("INSERT INTO People (First, Last) VALUES (@First, @Last)",
{| First = first
Last = last |})
interface IDisposable with
member _.Dispose() =
cn.Dispose()
let run() =
use connection = new SQLiteConnection("Data Source=:memory:;Version=3")
connection.Open()
connection.Execute("CREATE TABLE People (Id INTEGER PRIMARY KEY, First TEXT, Last TEXT)") |> ignore
use repo = new PersonRepo(connection)
let irepo = repo :> IPersonRepo // Casting because the interface has AddPerson and GetPeople, but the base class does not
irepo.AddPerson("John", "Smith") |> ignore
irepo.AddPerson("Jane", "Doe") |> ignore
let people = irepo.GetPeople()
for person in people do
printfn $"%O{person}"
run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment