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
Full name: CDocument.firstOrNone
from Microsoft.FSharp.Collections
Full name: Microsoft.FSharp.Collections.Seq.tryFind
Full name: CDocument.getGenres
Full name: Microsoft.FSharp.Collections.list<_>
Full name: Microsoft.FSharp.Collections.Seq.toList
Full name: CDocument.getAlbumsForGenre
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
Calls Linq.QueryBuilder.Join
Calls Linq.QueryBuilder.Where
Calls Linq.QueryBuilder.Select
Full name: CDocument.getAlbumDetails
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)