функция запроса с предикатом - PullRequest
1 голос
/ 24 мая 2011

Мьелло там! В данный момент я пытаюсь создать приложение F #, и теперь я столкнулся с другой стеной.

Проблема заключается в модуле Microsoft.FSharp.Linq.Query, функция query не будет принимать мои предикаты, если они передаются в качестве параметров. Проверьте это:

member x.GetUsersWhere (e:User -> bool) =
    query <@ ctx.Users |> Seq.filter e @>

и затем я называю это как:

let service = new UserService()
service.GetUsersWhere (fun z -> z.Name = "James")

Это должно быть хорошо, а? Ну, компилятор не согласен:

Следующая конструкция была использована в запрос, но не распознается Переводчик запросов F # -to-LINQ: Вызов (Никто, System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User] op_PipeRight[DbSet 1, IEnumerable 1](System.Data.Entity.DbSet 1 [WebFSharp.Entities.User], Microsoft.FSharp.Core.FSharpFunc 2[System.Data.Entity.DbSet 1 [WebFSharp.Entities.User], System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User]]), [PropertyGet (Some (FieldGet (Some (Value (WebFSharp.Business.UserService)), WebFSharp.Business.MyContext ctx)), System.Data.Entity.DbSet 1 [WebFSharp.Entities.User] Пользователи, []), Позвольте (предикат, Значение (), Лямбда (источник, Позвонить (нет, System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User] Filter[User](Microsoft.FSharp.Core.FSharpFunc 2 [WebFSharp.Entities.User, System.Boolean], System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User]), [predicate, Coerce (source, System.Collections.Generic.IEnumerable 1 [[WebFSharp.Entities.User, WebFSharp.Entities, версия = 0.0.0.0, Culture = нейтрально, PublicKeyToken = null]])])))]) Это недопустимое выражение запроса. Проверьте спецификация разрешенных запросов и рассмотреть возможность перемещения некоторых запросов вне предложения

Что происходит? Это потому, что Expr будет оцениваться до того, как в него будет введен параметр?

В любом случае, следующий код работает, но гораздо менее гибок:

member x.GetUsersByName name =
    query <@ ctx.Users |> Seq.filter(fun z -> z.Name = name) @>

let service = new UserService()
service.GetUsersByName "James"

Может ли кто-нибудь пролить свет на то, что происходит?

1 Ответ

8 голосов
/ 24 мая 2011

В вашем коде транслятор F # to LINQ не имеет никакого способа проверить указанную вами функцию (аргумент e - это некоторый скомпилированный код - нет способа получить его кавычное представление, которое можно было бы перевести в SQL).

Вам нужно использовать Expr<User -> bool> вместо User -> bool. Это означает, что вместо передачи функции вы передадите некоторое представление кода, используемого в качестве аргумента (который может быть проанализирован и переведен в SQL):

member x.GetUsersWhere (e:Expr<User -> bool>) = 
    query <@ ctx.Users |> Seq.filter %e @>

Обратите внимание на синтаксис %e - это означает, что код в кавычках должен быть встроен (объединен) в основное выражение в кавычках, поэтому переводчик видит его как одно выражение. При ее вызове вам также необходимо передать функцию с использованием кавычек:

let service = new UserService()service.GetUsersWhere <@ fun z -> z.Name = "James" @>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...