Best way to connect to MySQL and execute a query? (probably with Dapper)

I will preface with I simply could not get the Sql Type Provider to work – it threw a dozen different errors at points and seemed to be a version conflict. So I want to avoid that. I’ve been following mostly C# examples and can’t always get the syntax right in F#.

I am targeting .NET6 (though can drop to 5 if it’s going to be an issue).

I have modelled the data as a type as well.

I like the look of Dapper the best but I generally don’t need a full ORM and would just like to run raw SQL queries so am open to other solutions.

I have a MySQL server running and a connection string.

I would like to

  1. Initialize an SQL connection with my connection string.
  2. Execute a query (preferably in raw SQL). If a select query, map it to my data type.
  3. Be able to nearly execute more queries from elsewhere in the code without reinitializing a connection.

It’s really just a package and a syntax example of those three things that I need. Thanks.

Answer

This is an example where I’ve used Dapper to query an MS SQL Express database. I have quite a lot of helper methods that I’ve made trough the years in order to make Dapper (and to a slight degree also SqlClient) easy and type safe in F#. Below you see just two of these helpers – queryMultipleAsSeq and queryMultipleToList.

I realize now that it’s not that easy to get going with Dapper and F# unless these can be made available to others. I have created a repo on GitHub for this, which will be updated regularly with new helper functions and demos to show how they’re used.

The address is https://github.com/BentTranberg/DemoDapperStuff

Ok, now this initial demo:

module DemoSql.Main

open System
open System.Data.SqlClient
open Dapper
open Dapper.Contrib
open Dapper.Contrib.Extensions

let queryMultipleAsSeq<'T> (conn: SqlConnection, sql: string, args: obj) : 'T seq =
    conn.Query<'T> (sql, args)

let queryMultipleToList<'T> (conn: SqlConnection, sql: string, args: obj) : 'T list =
    queryMultipleAsSeq (conn, sql, args)
    |> Seq.toList

let connectionString = @"Server=.SqlExpress;Database=MyDb;User Id=sa;Password=password"
let [<Literal>] tableUser = "User"

[<Table (tableUser); CLIMutable>]
type EntUser =
    {
        Id: int
        UserName: string
        Role: string
        PasswordHash: string
    }

let getUsers () =
    use conn = new SqlConnection(connectionString)
    (conn, "SELECT * FROM " + tableUser, null)
    |> queryMultipleToList<EntUser>

[<EntryPoint>]
let main _ =
    getUsers ()
    |> List.iter (fun user -> printfn "Id=%d User=%s" user.Id user.UserName)
    Console.ReadKey() |> ignore
    0

The packages used for this demo:

<PackageReference Include="Dapper.Contrib" Version="2.0.78" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />

The Dapper.Contrib will drag along Dapper itself.