Как исправить пустые объекты, возвращаемые Giraffe API, полученные из БД через SqlDataProvider
Я пытаюсь изучить F#, создавая приложение F# с репозиторием для извлечения упражнений для будущего приложения Gym.
Я использую SqlServer для хранения данных и получаю данные с помощью Fsharp.Data.Sql. Модульные тесты для этого работают хорошо.
Я пытаюсь предоставить данные через веб-API с помощью Giraffe, проблема в том, что я возвращаю список с правильной длиной, но с пустыми объектами внутри.
Вот контекст:
module Context
open FSharp.Data.Sql
let [<Literal>] dbVendor = Common.DatabaseProviderTypes.MSSQLSERVER
let [<Literal>] connectionString = "Server=DESKTOP-20JMHNK;Database=GymStrongDB;Trusted_Connection=True;"
let [<Literal>] indivAmount = 1000
let [<Literal>] useOptTypes = true
let [<Literal>] owner = "public, admin, references"
type sql =
SqlDataProvider<
dbVendor,
connectionString,
"",
"",
indivAmount,
useOptTypes,
owner>
let gymStrongContext = sql.GetDataContext()
Вот репозиторий
namespace GymStrong.Repositories
open ...
module ExerciseRepository =
let ctx = gymStrongContext.Dbo
let getExercises =
ctx.Exercises |> Seq.toList
let getExercisesHandler : HttpHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
Successful.OK getExercises next ctx
А вот соответствующая часть из Program.fs
open ...
let webApp =
choose [
GET >=>
choose [
route "/" >=> text "Hello World"
route "/user" >=> mustBeLoggedIn >=> getLoggedInUser
route "/logout" >=> mustBeLoggedIn >=> logoutHandler
route "/exercises" >=> mustBeLoggedIn >=> getExercisesHandler
]
POST >=>
choose [
route "/register" >=> registerHandler
route "/login" >=> loginHandler
]
]
В юнит-тестах это работает правильно. Модульные тесты написаны на C#.
Когда я использую API через PostMan, я получаю такой ответ
[{},{}]
Который имеет правильную длину, так как у меня есть два упражнения в базе данных, но объекты кажутся пустыми.
1 ответ
Это может быть кому-то полезно, поэтому я опубликую его.
И Giraffe, и SqlDataProvider делают то, что должны. Проблема заключалась в том, что я думал, что могу передать предоставленный тип как json-ответ в API. Это неверно, поскольку предоставленные типы не являются настоящими типами и "стерты" (вместо "Сгенерированный" тип, с которым, как я думал, я работал).
Чтобы исправить это, мне нужно было сопоставить значения "настоящему" анемичному объекту DTO и передать его в качестве ответа. Теперь мне нужно выяснить, можно ли предоставить эти анемичные DTO-объекты на основе entityTypes и создать их и использовать из других сборок.
Дополнительный код:
В репозитории / сервисе
type exerciseDto = {
Id : string;
Name : string;
Description : string;
Owner : string;
Type : int;
}
let getExercises =
ctx.Exercises |> Seq.map(fun exercise -> exercise.MapTo<exerciseDto>()) |> Seq.toList
И в program.cs
let handlerWrapper action : HttpHandler =
fun (next : HttpFunc) (ctxHttp : HttpContext) ->
Successful.OK action next ctxHttp
let webApp =
choose [
GET >=>
choose [
route "/" >=> text "Hello World"
route "/user" >=> mustBeLoggedIn >=> getLoggedInUser
route "/logout" >=> mustBeLoggedIn >=> logoutHandler
route "/exercises" >=> mustBeLoggedIn >=> handlerWrapper getExercises
]
POST >=>
choose [
route "/register" >=> registerHandler
route "/login" >=> loginHandler
]
]
Надеюсь, это поможет кому-нибудь сэкономить время в будущем. На это у меня ушло как минимум несколько часов.