Dzoukr/Dapper.FSharp

SelectAsync returns a Task which cannot be wrapped in async block

DianaLaa opened this issue · 4 comments

This does not work:

namespace API.DAL.Authorization

open API.DAL
open Dapper.FSharp
open Dapper.FSharp.MSSQL
open Microsoft.Data.SqlClient
open System.Data

type public IAuthorizationRepository =
    abstract member ListModules : slug:string -> Async<string list>

type public AuthorizationRepository(connectionString: ConnectionString) =
    interface IAuthorizationRepository with
        member this.ListModules(slug: string) = 
            use connection: IDbConnection = new SqlConnection(connectionString.ConnectionString)
            let moduleTable = table<string>
            async {
                select {
                    for p in moduleTable do
                    selectAll
                } |> connection.SelectAsync<string>
                // ??? Compile error: Type constraint mismatch. The type Async<unit> is not compatible with type Async<string list>
            }

How to use Dapper.FSharp with async?

Use the new task block instead of async (or else convert the task to an async).
Also you will need to return!, or await the results with let! and then return them.

You should review this:
https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/async

Also, you should be calling connection.SelectAsync<MyModuleType>, where MyModuleType is the type you created to represent that table.

namespace API.DAL.Authorization

open API.DAL
open Dapper.FSharp
open Dapper.FSharp.MSSQL
open Microsoft.Data.SqlClient
open System.Data

type public IAuthorizationRepository =
    abstract member ListModules : slug:string -> Async<string list>

type public AuthorizationRepository(connectionString: ConnectionString) =
    interface IAuthorizationRepository with
        member this.ListModules(slug: string) = 
            use connection: IDbConnection = new SqlConnection(connectionString.ConnectionString)
            let moduleTable = table<string>
            task {
                let! modules =
                  select {
                      for p in moduleTable do
                      selectAll
                  } |> connection.SelectAsync<MyModuleType>

                return 
                  modules 
                  |> Seq.map (fun m -> m.Name)
            }

I don't think that's configured correctly either... I'm getting TaskCanceledException on connection.SelectAsync.
I'm sure I'm doing something wrong..

Ah, found it. The use connection statement should be inside the task.

Good catch!