Skip to content

Instantly share code, notes, and snippets.

@battermann
Last active October 24, 2015 18:06
Show Gist options
  • Save battermann/91e47e9c34da5701c7e0 to your computer and use it in GitHub Desktop.
Save battermann/91e47e9c34da5701c7e0 to your computer and use it in GitHub Desktop.

db scripts

CREATE TABLE [dbo].[UniqueIdentifier]
(
	[Typ] NVARCHAR(50) NOT NULL PRIMARY KEY,
	[CurrentMaxId] NVARCHAR(max) NOT NULL
)

seed

IF NOT EXISTS (SELECT 1 FROM [UniqueIdentifier] WHERE Typ = 'Issue')
BEGIN
	INSERT INTO [UniqueIdentifier]
	VALUES ('Issue', 'A000000')
END

generic UID generator - data access

module IdGeneratorDataAccess =
    open System
    open System.Data
    open System.Data.Linq
    open Microsoft.FSharp.Data.TypeProviders
    open Microsoft.FSharp.Linq
    open Chessie.ErrorHandling
    open System.Net
    open Microsoft.FSharp.Reflection
    open DomainModels

    [<Literal>]
    let connectionString = "Data Source=(localdb)\V11.0;Initial Catalog=BRAVE;Integrated Security=SSPI;"
    type private dbSchema = SqlDataConnection<connectionString>

    let private db (connectionString:string) = 
        let db = dbSchema.GetDataContext(connectionString)
        // Enable the logging of database activity to the console.
        db.DataContext.Log <- System.Console.Out
        db

    let getUid connectionString typ generateNextId =
        use conn = new System.Data.SqlClient.SqlConnection(connectionString);
        conn.Open()
        use tx = conn.BeginTransaction(IsolationLevel.Serializable)
        try
            let db = db connectionString
            let idOption = db.UniqueIdentifier |> Seq.tryFind (fun x -> x.Typ = typ)

            match idOption with
            | Some uid -> 
                let nextId = generateNextId uid.CurrentMaxId
                nextId |> Trial.lift (fun id ->
                    uid.CurrentMaxId <- id
                    db.DataContext.SubmitChanges()  
                    tx.Commit()
                    id)
            | None -> 
                tx.Rollback()
                fail (DbQueryError "Coud not generate id because could not find entry")
        with
        | ex -> 
            tx.Rollback()
            "Could not generate next id. " + ex.Message |> IdGenerationFailure |> fail

specific uid generator

let generateNextId (current:string) =
    let (|Int|_|) str =
        match System.Int32.TryParse(str) with
        | (true,int) -> Some(int)
        | _ -> None

    match current.Substring(1) with
    | Int i -> current.Substring(0, 1) + (i + 1).ToString().PadLeft(6, '0') |> ok
    | _ -> fail (IdGenerationFailure "Could not generate next id. Could not parse to int.")

composition

type Dependencies = { 
	ReadEvents: string -> string -> Result<(int*Event list), DomainMessage>
	ReadStreamIds: string -> Result<string list, DomainMessage>
	IssueIdProvider: unit -> Result<Id, DomainMessage> }

let deps = {
    ReadEvents = readStream
    ReadStreamIds = readStreamIds
    IssueIdProvider = fun () -> IssueId <!> getUid relDbConnectionString "Issue" IssueId.generateNextId }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment