Skip to content

Correct way to create reusable queries #108

@AP-Hunt

Description

@AP-Hunt

Hi folks,

I've got an interface to implement with methods like

GetById(id) : User
GetByName(name): User
GetByEmail(email) : User
GetByPhoneNumber(phoneNo): User

An implementation for any one of these might look like below, and each of them varies only in the where clause.

member this.GetById(id: string) =
    conn.SelectAync<User> <| select {
        from u in usersTable
        where (u.Id = id)
    }

I tried to write a small reusable function (below) to tidy things up, but I got a NotImplementedException from LinqExpressionVisitors.visitWhere on line 260

Relevant stack trace

Dapper.FSharp.SQLite.LinqExpressionVisitors.visit$cont@243-4(FSharpFunc<MemberInfo, string> qualifyColumn, Expression exp, BinaryExpression x, Unit unitVar) in C:\Dzoukr\Personal\Dapper.FSharp\src\Dapper.FSharp\SQLite\LinqExpressionVisitors.fs
Dapper.FSharp.SQLite.LinqExpressionVisitors.visit@200-30(FSharpFunc<MemberInfo, string> qualifyColumn, Expression exp) in C:\Dzoukr\Personal\Dapper.FSharp\src\Dapper.FSharp\SQLite\LinqExpressionVisitors.fs
Dapper.FSharp.SQLite.LinqExpressionVisitors.visitWhere<T>(Expression<Func<T, bool>> filter, FSharpFunc<MemberInfo, string> qualifyColumn) in C:\Dzoukr\Personal\Dapper.FSharp\src\Dapper.FSharp\SQLite\LinqExpressionVisitors.fs
Dapper.FSharp.SQLite.Builders+SelectExpressionBuilder<T>.Where(QuerySource<T> state, Expression<Func<T, bool>> whereExpression) in C:\Dzoukr\Personal\Dapper.FSharp\src\Dapper.FSharp\SQLite\Builders.fs

let findFirstBy<'t when 't: null> (conn: DbConnection) (tbl: QuerySource<'t>)  (expr: 't -> bool) =
    task {
        let xs! = conn.SelectAsync<'t> <| select {
            for x in tbl do
            where (expr x)
        }
        
        match Seq.length xs with
        | 0 -> return null
        | _ -> return Seq.head xs        
    }
    
...

member this.GetById(id: string) = findFirstBy conn usersTable (fun u -> u.Id = id)
member this.GetByName(name: string) = findFirstBy conn usersTable (fun u -> u.Name = name)

What would be the correct way of implementing this? Or am I pursuing something that Dapper.FSharp wasn't designed to support?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions