Queries

With the type aliases set up, we can move forward to creating our first queries:

let firstOrNone s = s |> Seq.tryFind (fun _ -> true) let getGenres (ctx : DbContext) : Genre list = ctx.``[dbo].[Genres]`` |> Seq.toList let getAlbumsForGenre genreName (ctx : DbContext) : Album list = query { for album in ctx.``[dbo].[Albums]`` do join genre in ctx.``[dbo].[Genres]`` on (album.GenreId = genre.GenreId) where (genre.Name = genreName) select album } |> Seq.toList let getAlbumDetails id (ctx : DbContext) : AlbumDetails option = query { for album in ctx.``[dbo].[AlbumDetails]`` do where (album.AlbumId = id) select album } |> firstOrNone
val firstOrNone : s:seq<'a> -> 'a option

Full name: CDocument.firstOrNone
val s : seq<'a>
module Seq

from Microsoft.FSharp.Collections
val tryFind : predicate:('T -> bool) -> source:seq<'T> -> 'T option

Full name: Microsoft.FSharp.Collections.Seq.tryFind
val getGenres : ctx:'a -> 'b list

Full name: CDocument.getGenres
val ctx : 'a
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
val getAlbumsForGenre : genreName:'a -> ctx:'b -> 'c list (requires equality)

Full name: CDocument.getAlbumsForGenre
val genreName : 'a (requires equality)
val ctx : 'b
val query : Linq.QueryBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
val album : 'c
custom operation: join var in collection on (outerKey = innerKey). Note that parentheses are required after 'on'

Calls Linq.QueryBuilder.Join
val genre : obj
custom operation: where (bool)

Calls Linq.QueryBuilder.Where
custom operation: select ('Result)

Calls Linq.QueryBuilder.Select
val getAlbumDetails : id:'a -> ctx:'b -> 'c option (requires equality)

Full name: CDocument.getAlbumDetails
val id : 'a (requires equality)
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>

getGenres is a function for finding all genres. The function, as well as all functions we'll define in Db module, takes the DbContext as a parameter. The : Genre list part is a type annotation, which makes sure the function returns a list of Genres. Implementation is straight forward: ctx.``[dbo].[Genres]`` queries all genres, so we just need to pipe it to the Seq.toList.

getAlbumsForGenre takes genreName as argument (inferred to be of type string) and returns a list of Albums. It makes use of "query expression" (query { }) which is very similar to C# Linq query. Read here for more info about query expressions. Inside the query expression, we're performing an inner join of Albums and Genres with the GenreId foreign key, and then we apply a predicate on genre.Name to match the input genreName. The result of the query is piped to Seq.toList.

getAlbumDetails takes id as argument (inferred to be of type int) and returns AlbumDetails option because there might be no Album with the given id. Here, the result of the query is piped to the firstOrNone function, which takes care to transform the result to option type. firstOrNone verifies if a query returned any result. In case of any result, firstOrNone will return Some x, otherwise None.


GitHub commit: 65b87efad69a8a92a622ba2fa3ac182e1e131cb7

Files changed:

  • Db.fs (modified)

results matching ""

    No results matching ""