Genres list

For more convenient instantiation of DbContext, let's introduce a small helper function in Db module:


let getContext() = Sql.GetDataContext()

Now we're ready to finally read real data in the App module:


let overview = warbler (fun _ -> Db.getContext() |> Db.getGenres |> (fun g -> g.Name) |> |> html)


path Path.Store.overview >=> overview

overview is a WebPart that... Hold on, do I really need to explain it? The usage of pipe operator here makes the flow rather obvious - each line defines each step. The return value is passed from one function to another, starting with DbContext and ending with the WebPart. This is just a single example of how composition in functional programming makes functions look like building blocks "glued" together.

We also had to wrap the overview WebPart in a warbler, because otherwise the overview WebPart would be in a sense static - there'd be no reason not to cache the result. warbler ensures that genres will be fetched from the database whenever a new request comes. Otherwise, without the warbler in place, the genres would be fetched only at the start of the application - resulting in stale genres in case the list changes.

Do we need also to wrap with warbler the rest of WebParts?

  • browse is parametrized with genre name - each request will result in a database query anyway, so we don't need to do anything here.
  • details is parametrized with the id - same as above.
  • home is just fine - for the moment it's completely static and doesn't need to touch the database.
    Multiple items
    namespace FSharp

    namespace Microsoft.FSharp
    Multiple items
    namespace FSharp.Data

    namespace Microsoft.FSharp.Data
    namespace FSharp.Data.Sql
    Multiple items
    type LiteralAttribute =
    inherit Attribute
    new : unit -> LiteralAttribute

    Full name: Microsoft.FSharp.Core.LiteralAttribute

    new : unit -> LiteralAttribute
    val ConnectionString : string

    Full name: SuaveMusicStore.Db.ConnectionString
    type Sql = SqlDataProvider<...>

    Full name: SuaveMusicStore.Db.Sql
    type SqlDataProvider

    Full name: FSharp.Data.Sql.SqlDataProvider

    <summary>Typed representation of a database</summary>
    <param name='ConnectionString'>The connection string for the SQL database</param>
    <param name='ConnectionStringName'>The connection string name to select from a configuration file</param>
    <param name='DatabaseVendor'> The target database vendor</param>
    <param name='IndividualsAmount'>The amount of sample entities to project into the type system for each SQL entity type. Default 1000.</param>
    <param name='UseOptionTypes'>If true, F# option types will be used in place of nullable database columns. If false, you will always receive the default value of the column's type even if it is null in the database.</param>
    <param name='ResolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types.</param>
    <param name='Owner'>The owner of the schema for this provider to resolve (Oracle Only)</param>
    <param name='CaseSensitivityChange'>Should we do ToUpper or ToLower when generating table names?</param>
    <param name='TableNames'>Comma separated table names list to limit a number of tables in big instances. The names can have '%' sign to handle it as in the 'LIKE' query (Oracle and MSSQL Only)</param>
    <param name='OdbcQuote'>Odbc quote characters: Quote characters for the table and column names: `alias`, [alias]</param>
    <param name='SQLiteLibrary'>Use System.Data.SQLite or Mono.Data.SQLite or select automatically (SQLite only)</param>
    namespace FSharp.Data.Sql.Common
    type DatabaseProviderTypes =
    | SQLITE = 1
    | POSTGRESQL = 2
    | MYSQL = 3
    | ORACLE = 4
    | MSACCESS = 5
    | ODBC = 6
    | FIREBIRD = 7

    Full name: FSharp.Data.Sql.Common.DatabaseProviderTypes
    Common.DatabaseProviderTypes.POSTGRESQL: Common.DatabaseProviderTypes = 2
    type CaseSensitivityChange =
    | ORIGINAL = 0
    | TOUPPER = 1
    | TOLOWER = 2

    Full name: FSharp.Data.Sql.Common.CaseSensitivityChange
    Common.CaseSensitivityChange.ORIGINAL: Common.CaseSensitivityChange = 0
    type DbContext = SqlDataProvider<...>.dataContext

    Full name: SuaveMusicStore.Db.DbContext
    type dataContext =
    member ClearUpdates : unit -> List<SqlEntity>
    member CreateConnection : unit -> IDbConnection
    member GetUpdates : unit -> List<SqlEntity>
    member Public : publicSchema
    member SubmitUpdates : unit -> Unit
    member SubmitUpdatesAsync : unit -> Async<Unit>
    nested type public.albumdetails.Individuals
    nested type public.albumdetailsEntity
    nested type public.albums.Individuals
    nested type public.albumsEntity

    Full name: FSharp.Data.Sql.SqlDataProvider,DatabaseVendor="2",ConnectionString="Server=;Database=suavemusicstore;User Id=suave;Password=1234;",CaseSensitivityChange="0".dataContext
    type Album = SqlDataProvider<...>.dataContext.public.albumsEntity

    Full name: SuaveMusicStore.Db.Album
    type Genre = SqlDataProvider<...>.dataContext.public.genresEntity

    Full name: SuaveMusicStore.Db.Genre
    type AlbumDetails = SqlDataProvider<...>.dataContext.public.albumdetailsEntity

    Full name: SuaveMusicStore.Db.AlbumDetails
    val getContext : unit -> SqlDataProvider<...>.dataContext

    Full name: SuaveMusicStore.Db.getContext
    SqlDataProvider<...>.GetDataContext() : SqlDataProvider<...>.dataContext

    <summary>Returns an instance of the SQL Provider using the static parameters</summary>

    SqlDataProvider<...>.GetDataContext(transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext

    <summary>Returns an instance of the SQL Provider</summary>
    <param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>

    SqlDataProvider<...>.GetDataContext(connectionString: string) : SqlDataProvider<...>.dataContext

    <summary>Returns an instance of the SQL Provider</summary>
    <param name='connectionString'>The database connection string</param>

    SqlDataProvider<...>.GetDataContext(connectionString: string, transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext

    <summary>Returns an instance of the SQL Provider</summary>
    <param name='connectionString'>The database connection string</param>
    <param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>

    SqlDataProvider<...>.GetDataContext(connectionString: string, resolutionPath: string) : SqlDataProvider<...>.dataContext

    <summary>Returns an instance of the SQL Provider</summary>
    <param name='connectionString'>The database connection string</param>
    <param name='resolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types</param>

    SqlDataProvider<...>.GetDataContext(connectionString: string, resolutionPath: string, transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext

    <summary>Returns an instance of the SQL Provider</summary>
    <param name='connectionString'>The database connection string</param>
    <param name='resolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types</param>
    <param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>
    val getGenres : ctx:DbContext -> Genre list

    Full name: SuaveMusicStore.Db.getGenres
    val ctx : DbContext
    type 'T list = List<'T>

    Full name: Microsoft.FSharp.Collections.list<_>
    property SqlDataProvider<...>.dataContext.Public: SqlDataProvider<...>.dataContext.publicSchema
    property SqlDataProvider<...>.dataContext.publicSchema.Genres: SqlDataProvider<...>.dataContext.publicSchema.public.genres

    <summary> The base table genres belonging to schema public</summary>
    Multiple items
    module Seq

    from FSharp.Data.Sql

    module Seq

    from Microsoft.FSharp.Collections
    val toList : source:seq<'T> -> 'T list

    Full name: Microsoft.FSharp.Collections.Seq.toList
    val getAlbumsForGenre : genreName:string -> ctx:DbContext -> Album list

    Full name: SuaveMusicStore.Db.getAlbumsForGenre
    val genreName : string
    val query : Linq.QueryBuilder

    Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
    val album : SqlDataProvider<...>.dataContext.public.albumsEntity
    property SqlDataProvider<...>.dataContext.publicSchema.Albums: SqlDataProvider<...>.dataContext.publicSchema.public.albums

    <summary> The base table albums belonging to schema public</summary>
    custom operation: join var in collection on (outerKey = innerKey). Note that parentheses are required after 'on'

    Calls Linq.QueryBuilder.Join
    val genre : SqlDataProvider<...>.dataContext.public.genresEntity
    property SqlDataProvider<...>.dataContext.public.genresEntity.Genreid: int

    <summary> integer</summary>
    custom operation: where (bool)

    Calls Linq.QueryBuilder.Where
    property SqlDataProvider<...>.dataContext.public.genresEntity.Name: string

    <summary> character varying(120)</summary>
    custom operation: select ('Result)

    Calls Linq.QueryBuilder.Select
    val getAlbumDetails : id:int -> ctx:DbContext -> AlbumDetails option

    Full name: SuaveMusicStore.Db.getAlbumDetails
    val id : int
    type 'T option = Option<'T>

    Full name: Microsoft.FSharp.Core.option<_>
    val album : SqlDataProvider<...>.dataContext.public.albumdetailsEntity
    property SqlDataProvider<...>.dataContext.publicSchema.Albumdetails: SqlDataProvider<...>.dataContext.publicSchema.public.albumdetails

    <summary> The view albumdetails belonging to schema public</summary>
    property SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Albumid: int

    <summary> integer</summary>
    val tryHead : source:seq<'T> -> 'T option

    Full name: Microsoft.FSharp.Collections.Seq.tryHead
    type IntPath = PrintfFormat<(int -> string),unit,string,string,int>

    Full name: SuaveMusicStore.Path.IntPath
    Multiple items
    type PrintfFormat<'Printer,'State,'Residue,'Result> =
    new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>
    member Value : string

    Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_>

    type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> =
    inherit PrintfFormat<'Printer,'State,'Residue,'Result>
    new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>

    Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_,_>

    new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>

    new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>
    Multiple items
    val int : value:'T -> int (requires member op_Explicit)

    Full name:

    type int = int32

    Full name:

    type int<'Measure> = int

    Full name:<_>
    Multiple items
    val string : value:'T -> string

    Full name: Microsoft.FSharp.Core.Operators.string

    type string = System.String

    Full name: Microsoft.FSharp.Core.string
    type unit = Unit

    Full name: Microsoft.FSharp.Core.unit
    val withParam : key:string * value:string -> path:string -> string

    Full name: SuaveMusicStore.Path.withParam
    val key : string
    val value : string
    val path : string
    val sprintf : format:Printf.StringFormat<'T> -> 'T

    Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
    val home : string

    Full name: SuaveMusicStore.Path.home
    module Store

    from SuaveMusicStore.Path
    val overview : string

    Full name: SuaveMusicStore.Path.Store.overview
    val browse : string

    Full name: SuaveMusicStore.Path.Store.browse
    val details : IntPath

    Full name: SuaveMusicStore.Path.Store.details
    val browseKey : string

    Full name: SuaveMusicStore.Path.Store.browseKey
    namespace Suave
    module Html

    from Suave
    val cssLink : href:string -> Node

    Full name: SuaveMusicStore.View.cssLink
    val href : string
    val link : attr:Attribute list -> Node

    Full name:
    val h2 : s:string -> Node

    Full name: SuaveMusicStore.View.h2
    val s : string
    val tag : tag:string -> attr:Attribute list -> contents:Node list -> Node

    Full name: Suave.Html.tag
    union case Node.Text: string -> Node
    val ul : nodes:Node list -> Node

    Full name: SuaveMusicStore.View.ul
    val nodes : Node list
    val li : (Node list -> Node)

    Full name:
    val home : Node list

    Full name: SuaveMusicStore.View.home
    val store : genres:string list -> Node list

    Full name:
    val genres : string list
    val p : (Attribute list -> Node list -> Node)

    Full name: Suave.Html.p
    Multiple items
    module List

    from Microsoft.FSharp.Collections

    type List<'T> =
    | ( [] )
    | ( :: ) of Head: 'T * Tail: 'T list
    interface IEnumerable
    interface IEnumerable<'T>
    member GetSlice : startIndex:int option * endIndex:int option -> 'T list
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    member Tail : 'T list
    static member Cons : head:'T * tail:'T list -> 'T list
    static member Empty : 'T list

    Full name: Microsoft.FSharp.Collections.List<_>
    val length : list:'T list -> int

    Full name: Microsoft.FSharp.Collections.List.length
    val genre : string
    val url : string
    module Path

    from SuaveMusicStore
    val a : href:string -> attr:Attribute list -> (Node list -> Node)

    Full name: Suave.Html.a
    val browse : genre:string -> Node list

    Full name: SuaveMusicStore.View.browse
    val details : id:int -> Node list

    Full name: SuaveMusicStore.View.details
    val index : container:Node list -> string

    Full name: SuaveMusicStore.View.index
    val container : Node list
    val html : (Attribute list -> Node list -> Node)

    Full name: Suave.Html.html
    val head : (Attribute list -> Node list -> Node)

    Full name: Suave.Html.head
    val title : attr:Attribute list -> s:string -> Node

    Full name: Suave.Html.title
    val body : (Attribute list -> Node list -> Node)

    Full name: Suave.Html.body
    val div : (Attribute list -> Node list -> Node)

    Full name: Suave.Html.div
    val htmlToString : node:Node -> string

    Full name: Suave.Html.htmlToString
    module App

    from SuaveMusicStore
    module Filters

    from Suave
    module Operators

    from Suave
    module RequestErrors

    from Suave
    module Successful

    from Suave
    module Web

    from Suave
    val html : container:Html.Node list -> WebPart

    Full name: SuaveMusicStore.App.html
    val container : Html.Node list
    val OK : body:string -> WebPart

    Full name: Suave.Successful.OK
    module View

    from SuaveMusicStore
    val index : container:Html.Node list -> string

    Full name: SuaveMusicStore.View.index
    val browse : (HttpContext -> Async<HttpContext option>)

    Full name: SuaveMusicStore.App.browse
    val request : apply:(HttpRequest -> HttpContext -> 'a) -> context:HttpContext -> 'a

    Full name: Suave.Http.request
    val r : HttpRequest
    member HttpRequest.queryParam : key:string -> Choice<string,string>
    union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
    val browse : genre:string -> Html.Node list

    Full name: SuaveMusicStore.View.browse
    union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
    val msg : string
    val BAD_REQUEST : body:string -> WebPart

    Full name: Suave.RequestErrors.BAD_REQUEST
    val overview : (HttpContext -> Async<HttpContext option>)

    Full name: SuaveMusicStore.App.overview
    val warbler : f:('t -> 't -> 'u) -> 't -> 'u

    Full name: Suave.WebPart.warbler
    module Db

    from SuaveMusicStore
    val getContext : unit -> FSharp.Data.Sql.SqlDataProvider<...>.dataContext

    Full name: SuaveMusicStore.Db.getContext
    val getGenres : ctx:Db.DbContext -> Db.Genre list

    Full name: SuaveMusicStore.Db.getGenres
    val map : mapping:('T -> 'U) -> list:'T list -> 'U list

    Full name:
    val g : Db.Genre
    property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.genresEntity.Name: string

    <summary> character varying(120)</summary>
    val store : genres:string list -> Html.Node list

    Full name:
    val webPart : WebPart<HttpContext>

    Full name: SuaveMusicStore.App.webPart
    val choose : options:WebPart<'a> list -> WebPart<'a>

    Full name: Suave.WebPart.choose
    val path : pathAfterDomain:string -> WebPart

    Full name: Suave.Filters.path
    val home : Html.Node list

    Full name: SuaveMusicStore.View.home
    val pathScan : pf:PrintfFormat<'a,'b,'c,'d,'t> -> h:('t -> WebPart) -> WebPart

    Full name: Suave.Filters.pathScan
    val details : Path.IntPath

    Full name: SuaveMusicStore.Path.Store.details
    val details : id:int -> Html.Node list

    Full name: SuaveMusicStore.View.details
    val pathRegex : pathAfterDomainRegex:string -> WebPart

    Full name: Suave.Filters.pathRegex
    module Files

    from Suave
    val browseHome : WebPart

    Full name: Suave.Files.browseHome
    val startWebServer : config:SuaveConfig -> webpart:WebPart -> unit

    Full name: Suave.Web.startWebServer
    val defaultConfig : SuaveConfig

    Full name: Suave.Web.defaultConfig

Show code from this section on GitHub

results matching ""

    No results matching ""