Skip to content

Instantly share code, notes, and snippets.

@SCullman
Last active February 15, 2021 21:59
Show Gist options
  • Save SCullman/8f1b5d1ff123f1b50797ee1ae3c60469 to your computer and use it in GitHub Desktop.
Save SCullman/8f1b5d1ff123f1b50797ee1ae3c60469 to your computer and use it in GitHub Desktop.
PetaPoco and F# Options
namespace PetaPoco.FSharpOptions
open PetaPoco
open System
type OptionConverterAttribute() =
inherit ValueConverterAttribute()
with
override __.ConvertFromDb(value: obj) =
let toOption (v: 'T) =
(if (isNull v) then None else Some v) |> box
let nullableToOption (n: System.Nullable<_>) =
(if n.HasValue then
Some n.Value
else
None)
|> box
match value with
| :? string as s -> toOption s
| :? (Nullable<char>) as c -> nullableToOption c
| :? (Nullable<bool>) as i -> nullableToOption i
| :? (Nullable<int>) as i -> nullableToOption i
| :? (Nullable<uint>) as i -> nullableToOption i
| :? (Nullable<int64>) as i -> nullableToOption i
| :? (Nullable<float>) as i -> nullableToOption i
| :? (Nullable<float32>) as i -> nullableToOption i
| :? (Nullable<decimal>) as i -> nullableToOption i
| :? (Nullable<DateTime>) as i -> nullableToOption i
| :? (Nullable<DateTimeOffset>) as i -> nullableToOption i
| :? (Nullable<Guid>) as i -> nullableToOption i
| _ -> failwith "Converter not implemented"
override __.ConvertToDb(value: obj) =
let nullOrValue v =
match v with
| Some v -> box v
| _ -> null
match value with
| :? (Option<string>) as v -> nullOrValue v
| :? (Option<char>) as v -> nullOrValue v
| :? (Option<bool>) as v -> nullOrValue v
| :? (Option<int>) as v -> nullOrValue v
| :? (Option<uint>) as v -> nullOrValue v
| :? (Option<int64>) as v -> nullOrValue v
| :? (Option<float>) as v -> nullOrValue v
| :? (Option<float32>) as v -> nullOrValue v
| :? (Option<decimal>) as v -> nullOrValue v
| :? (Option<DateTime>) as v -> nullOrValue v
| :? (Option<DateTimeOffset>) as v -> nullOrValue v
| :? (Option<Guid>) as v -> nullOrValue v
| _ -> failwith "Converter not implemented"
type OptionMapper() =
inherit PetaPoco.StandardMapper()
let isOption (p: System.Reflection.PropertyInfo) =
p.PropertyType.IsGenericType
&& p.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>>
override __.GetFromDbConverter
(
targetProperty: System.Reflection.PropertyInfo,
sourceType: System.Type
): System.Func<obj, obj> =
if (isOption targetProperty) then
System.Func<obj, obj>(OptionConverterAttribute().ConvertFromDb)
else
null
override __.GetToDbConverter(sourceProperty: System.Reflection.PropertyInfo): System.Func<obj, obj> =
if (isOption sourceProperty) then
System.Func<obj, obj>(OptionConverterAttribute().ConvertToDb)
else
null
[<CLIMutable>]
type T =
{ Id: int
Text: string option
Integer: int option
Date: DateTime option }
//the mapper is always for the "class"
PetaPoco.Mappers.Register(typeof<T>, OptionMapper()) |> ignore
let db = new PetaPoco.Database("petapoco")
let t = { Id =22; Text =Some "22" ; Integer= None ; Date = None}
db.Insert t |> ignore
let ts = db.Fetch<T>() |> Seq.toList
[<CLIMutable>]
type T =
{ Id: int
[<OptionConverter>]
Text: string option
[<OptionConverter>]
Integer: int option
[<OptionConverter>]
Date: DateTime option }
let db = new PetaPoco.Database("petapoco")
let t = { Id =22; Text =Some "22" ; Integer= None ; Date = None}
db.Insert t |> ignore
let ts = db.Fetch<T>() |> Seq.toList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment