Question

I'm just starting out with F# and .Net but after some Googling I didn't find examples of this. I apologize in advance if this is too simple.

I'm trying to query a database and do it asynchronously. For example, I have a function like so:

let queryExample name = 
    query {for f in foo do
           where (f.name = name)
           select f.name}
    |> Seq.toList

Now, how would I make an async version of this? query doesn't return an Async<'a> type.

Was it helpful?

Solution

The answer will depend on what you're querying. Many data sources will expose something like a data context that enables running queries in different ways, but this isn't exposed directly on the IQueryable type (and is therefore not something that you can do directly with the result of a query { ... } expression.

As an example, if your foo is a LINQ-to-SQL Table<Foo>, then you can do something like this:

let queryExample name =
    let q = 
        query { for f in foo do
                where (f.name = name)
                select f.name }
    let cmd = foo.Context.GetCommand(q)
    async {
        let! reader = Async.AwaitTask (cmd.ExecuteReaderAsync())
        return foo.Context.Translate<Foo>(reader)
    }

This will return an Async<seq<Foo>>. If you'll be running lots of queries like this, then it's easy to extract the meat of this into a reusable mechanism.

OTHER TIPS

I use FSharp.Data.Sql with success http://fsprojects.github.io/SQLProvider/ Seq.executeQueryAsync

Example below shows an easy syntax for doing this. Basically just create an async function with a query expression inside and return the result.

let data = [ 1; 5; 7; 11; 18; 21]

let getEvenInts = fun (arr : list<int> ) -> async {
    let q = query {        
      for N in arr do
      where (( N % 2 ) = 0)
      select N
    }
    return q
  }

let getOddInts = fun (arr : list<int> ) -> async {
    let q = query {        
      for N in arr do
      where (( N % 2 ) <> 0)
      select N
    }
    return q
  }

let evens = getEvenInts data |> Async.RunSynchronously
let odds = getOddInts data |> Async.RunSynchronously

printfn "Evens: %A Odds: %A" evens odds
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top