Stateモナドでコネクション管理

これは結構使える!かも。

open System
open System.Transactions
open FSharp.Monad.State
open Soma.Core

let config =
{ new MsSqlConfig() with
member
this.ConnectionString = "Data Source=.;Initial Catalog=Soma.Tutorial;Integrated Security=True" }

let getConnection() = state {
let! conOption = getState
let con =
match conOption with
| Some con -> con
| _ -> LocalDb.createConnection config
do! putState (Some con)
return con }

let find<'T when 'T : not struct> id = state {
let! con = getConnection()
return LocalDb.find<'T> config con id }

let insert<'T when 'T : not struct> entity = state {
let! con = getConnection()
return LocalDb.insert<'T> config con entity }

let update<'T when 'T : not struct> entity = state {
let! con = getConnection()
return LocalDb.update<'T> config con entity }

let delete<'T when 'T : not struct> entity = state {
let! con = getConnection()
LocalDb.delete<'T> config con entity }

let requiredTx m =
use tx = new TransactionScope(TransactionScopeOption.Required)
let result = eval m None
tx.Complete()
result

type Employee =
{ [<Id(IdKind.Identity)>]
EmployeeId : int
EmployeeName : string
DepartmentId : int
[<Version>]
VersionNo : int }

let exec2 emp = state {
do! delete emp }

let exec() = state {
let! emp = insert { EmployeeId = 0; EmployeeName = "Allen"; DepartmentId = 2; VersionNo = 0}
let! emp = find<Employee> [emp.EmployeeId]
let! emp = update { emp with EmployeeName = "Hoge" }
do! exec2 emp
return emp }

exec()

> requiredTx
> printfn "%A"

Console.ReadKey() |> ignore