Я хочу с нетерпением загрузить некоторые записи и их отношения из базы данных примерно так:
let getEmails() =
let emails =
(query { for q in entities.QueueItems do
select q.Email
take batchSize }
).Include(fun (e:Email) -> e.QueueItem)
|> Seq.toArray
emails
|> Array.iter (fun e -> entities.QueueItems.Remove(e.QueueItem) |> ignore)
entities.SaveChanges(logger) |> ignore
emails
Это прекрасно работает, хотя мне приходится заключать выражение запроса в скобки, чтобы иметь возможность вызывать для него include, что выглядит немного странно. Я задался вопросом, могу ли я написать вспомогательную функцию для вызова Include в более идиоматичном стиле F#, и я придумал это.
module Ef =
let Include (f:'a -> 'b) (source:IQueryable<'a>) =
source.Include(f)
теперь мой запрос может выглядеть так (вывод типа работает с запрашиваемым типом: D)
let emails =
query { for q in entities.QueueItems do
select q.Email
take batchSize }
|> Ef.Include(fun e -> e.QueueItem)
|> Seq.toArray
Он компилируется! Но когда я запускаю его, я получаю сообщение об ошибке из библиотеки DbExtensions, говорящее мне The Include path expression must refer to a navigation property defined on the type.
Проверка лямбда-функции перед ее передачей в Queryable.Include выглядит так {<StartupCode$Service>.$Worker.emails@30} Microsoft.FSharp.Core.FSharpFunc<Entities.Email,Entities.QueueItem> {<StartupCode$Service>.$Worker.emails@30}
.
Я предполагаю, что проблема связана с тем, как интерпретируется моя лямбда и преобразованиями между FSharpFunc
s и Expression<Func<>>
s. Я попытался переписать свою вспомогательную функцию, чтобы она имела Expression<Func<'a, 'b>>
в качестве первого параметра, и даже загрузил исходный код FSharp.Core, чтобы найти вдохновение в реализациях модуля Seq и QueryBuilder, но у меня ничего не получилось. Я попытался переопределить свою вспомогательную функцию следующим образом:
module Ef =
let Include (y:Expression<Func<'a,'b>>) (source:IQueryable<'a>) =
source.Include(y)
Но потом я получаю ошибку компилятора This function takes too many arguments, or is used in a context where a function is not expected
.
Я немного озадачен. Может ли кто-нибудь предложить, как я могу заставить это работать?