Dzoukr / Dapper.FSharp

Lightweight F# extension for StackOverflow Dapper with support for MSSQL, MySQL, PostgreSQL, and SQLite
MIT License
365 stars 35 forks source link

Query expressions #24

Closed JordanMarr closed 3 years ago

JordanMarr commented 3 years ago

I’ve been trying to find the perfect ORM to complement SqlHydra. Unfortunately, I can’t find much in the way of current F# ORMs with strongly typed query expressions that work with records.

Dapper.FSharp is my favorite candidate so far due to its simplicity and the fact that it targets F# first and foremost and has great support for records. In conjunction with SqlHydra generating the entity records, I think it would be very nice if it featured strongly typed query expressions. This would make it the perfect complement.

So I just wanted to check to see if this is a PR that you might be interested in. I’m imagining a strongly typed version of the select query expression that would feed into the current select CE.

If you would prefer to keep Dapper.FSharp super simple and avoid adding this, I totally understand. In that case, I think this could also be a good candidate for a separate NuGet package that augments Dapper.FSharp as a dependency (similar to libs like Dapper.Contrib). Of course that also could get kind of ridiculous since it would essentially be an addon to an addon. 😄

Dzoukr commented 3 years ago

Hmmmm. 🤔 Sounds interesting. Please, could you provide a short sample of how it would look like before I take a decision on this? I tend to have this library as simple as possible (for known reasons), but don't want to kill a good idea which could be a great "addon-to-an-addon" 😄

JordanMarr commented 3 years ago

Sure!

Given this example:

select {
    table "Persons"
    where (gt "Position" 5 + lt "Position" 10)
} |> conn.SelectAsync<Person>

I was imagining something like this:

select {
    for p in tbl<Persons>()
    where (p.Position > 5 && p.Position < 10)
    orderBy p.LName
} |> conn.SelectAsync<Persons>

SqlHydra names records after the table and properties after the columns, so they should already match. (The tbl<Persons>() is off the top of my head. There may be a cleaner way to do that. In fact it could maybe even just be tbl since the entity type can be inferred via conn.SelectAsync<Persons>.)

I was imagining that the expression based select CE could require opening a separate namespace.

That's the idea at least.. Of course all of this would need to pass a proof of concept phase on a very simple query before tackling the full query expression tree.

Dzoukr commented 3 years ago

I like it.

I was imagining that the expression based select CE could require opening a separate namespace.

Yup, that's the way IMO. I think a separate module would be great.