F # query expressions

I study F#and now read about calculation expressions and query expressions for use with SQL type providers. I did some simple tasks, and at some point needed to concatenate (Union) 2 queries, my first thought after reading yieldin sequences and lists was to do the same inside the query expression, like this:

query {
    yield! for a in db.As select { // projection }
    yield! for b in db.Bs select { // projection }
}

it was the wrong code, then my second approach was to "concat" them to use:

seq {
    yield! query {...}
    yield! query {...}
}

or using Linq function Concatas follows: (query {...}).Concat(query {...}). How to do this is the answer question

Both of the above approaches work with the same difference, but when used, seq2 SQL queries will be executed, and Concatonly one will be executed , which is understandable.

Then my question is: why is it not supported yieldin query expressions?


EDIT:

After further investigation I got to the MSDN documentation , and I saw the implemented methods yield, and YieldFrom, but Combine, and Delaythat is even more confusing to me now

+4
source share
2 answers

yield!It is supported to some extent in requests and can be used where it is selectusually:

query { 
    for x in [5;2;0].AsQueryable() do 
    where (x > 1)
    sortBy x
    yield! [x; x-1] 
 } |> Seq.toList // [2;1;5;4]

, , , , :

query {
    for x in [1;2;3] do
    where (x > 1)
    while true do // error: can't use while (what would it mean?)
    sortBy x 
}

:

query {
    for x in [1;2;3] do
    where (x > 1)
    sortBy x 
    yield! ['a';'b';'c']
    yield! ['x';'y';'z'] // error
}        

, , yield! for .

, .

, -, , , , , . , , concat, , :

open System.Linq

type QB() =
    member inline x.Yield v = (Seq.singleton v).AsQueryable()
    member inline x.YieldFrom q = q
    [<CustomOperation("where", MaintainsVariableSpace=true)>]
    member x.Where(q:IQueryable<_>, [<ProjectionParameter>]c:Expressions.Expression<System.Func<_,_>>) = q.Where(c)
    [<CustomOperation("sortBy", MaintainsVariableSpace=true)>]
    member x.SortBy(q:IQueryable<_>, [<ProjectionParameter>]c:Expressions.Expression<System.Func<_,_>>) = q.OrderBy(c)
    [<CustomOperation("select")>]
    member x.Select(q:IQueryable<_>, [<ProjectionParameter>]c:Expressions.Expression<System.Func<_,_>>) = q.Select(c)
    [<CustomOperation("concat")>]
    member x.Concat(q:IQueryable<_>, q') = q.Concat(q')
    member x.For(q:IQueryable<'t>, c:'t->IQueryable<'u>) = q.SelectMany(fun t -> c t :> seq<_>) // TODO: implement something more reasonable here

let qb = QB()

qb {
    for x in ([5;2;0].AsQueryable()) do
    where (x > 1)
    sortBy x
    select x
    concat ([7;8;9].AsQueryable())
} |> Seq.toList
+2

F #: https://msdn.microsoft.com/en-us/library/hh225374.aspx

, , , :

let query1 = query {
        for n in db.Student do
        select (n.Name, n.Age)
    }

let query2 = query {
        for n in db.LastStudent do
        select (n.Name, n.Age)
        }

query2.Union (query1)
+1

Source: https://habr.com/ru/post/1612289/


All Articles