自定义EF F#查询转换器

For*_*VeR 10 linq f# entity-framework

在回答我的另一个问题时,我被告知用它QueryExtensions来实现与F#和实体框架的异步计算,并且我成功地使用了这个建议.

例如,我有以下功能:

let headAsync query =
    query
    |> QueryableExtensions.FirstAsync
    |> Async.AwaitTask
Run Code Online (Sandbox Code Playgroud)

可以这样使用:

async {
    let! entity =
        query {
            for e in context.MyEntities do
            sortBy e.Id
        } |> headAsync
    return entity
}
Run Code Online (Sandbox Code Playgroud)

尽管使用我的新函数作为查询表达式会很好.我写过:

type QueryBuilderEx() =
    inherit Linq.QueryBuilder()

    [<CustomOperation("headAsync")>]
    member __.HeadAsync<'T, 'Q when 'Q :> System.Linq.IQueryable<'T>> (source: Linq.QuerySource<'T, 'Q>) : Async<'T> =
        let queryable = source.Source :?> 'Q
        queryable.FirstOrDefaultAsync() |> Async.AwaitTask

let query2 = QueryBuilderEx()
Run Code Online (Sandbox Code Playgroud)

并试图像这样使用它:

async {
    let! entity =
        query2 {
            for e in context.MyEntities do
            sortBy e.Id
            headAsync
        }
    return entity
}
Run Code Online (Sandbox Code Playgroud)

此代码编译良好,但在运行时抛出以下异常:

System.NotSupportedException:这不是有效的查询表达式.方法'Microsoft.FSharp.Control.FSharpAsync`1 [Entities.MyEntity] HeadAsync [MyEntity,IQueryable`1](Microsoft.FSharp.Linq.QuerySource`2 [Entities.MyEntity,System.Linq.IQueryable`1 [Entities. MyEntity]])'在查询中使用但F#-to-LINQ查询转换器无法识别.检查允许的查询的规范,并考虑将一些操作移出查询表达式

那么,标准LINQ翻译器的扩展是可能的,或者我应该坚持我以前的headAsync实现形式的普通函数而不会搞乱QueryBuilder