AsyncSeq не печатает на консоли в интерактиве - PullRequest
1 голос
/ 30 октября 2019

Я определил простой тип записи

type RowSapPL = { CargoID: int; Currency: string; IsInternal: bool; Amount: decimal}

, и у меня есть несколько функций, очищающих таблицу

let emptySapPl () =
    asyncSeq {
        try
            let! dels =   
                query {
                 for pl in context.OilPhysical.SapPl do 
                 where (true)
                } |> Seq.``delete all items from single table``
            return Ok (dels, "deleted")
        with 
        | exc -> 
            return Error (exc.Message, "emptySapPl failed")
    }

и вставляющих новые строки с помощью поставщика типа Sql.

let loadSapPL (rows:RowSapPL[]) : AsyncSeq<Result<int * string, string * string>> = 
    asyncSeq {
        try
            rows
            |> Array.iter( fun r ->
                context.OilPhysical.SapPl.``Create(Amount, CargoID, Currency, InternalCurr)`` (r.Amount, r.CargoID, r.Currency, r.IsInternal) |> ignore
            )
            do! context.SubmitUpdatesAsync()
            return Ok (rows |> Array.length, "inserted")
        with
        | exc ->
            return Error (exc.Message, "loadSapPL failed") 
    }

В заключение я предоставляю API, который обрабатывает записи в виде фрагментов

type DB() =
    member x.loadSapPL (rows:RowSapPL[])  : AsyncSeq<Result<int * string, string * string>> = 
        asyncSeq {
            yield! emptySapPl()
            let chunks = rows |> Array.chunkBySize 500
            for chunk in chunks do
                yield! loadSapPL chunk
        }

, и я делаю быстрый тест в F # интерактив

let action (res: Result<int * string, string * string>) = 
    async  {
        match res with
        | Ok (i,m) -> printfn "*** Ok %d %s *** " i m
        | Error (m,e) -> printfn "*** Error %s %s *** " m e
    }

try
    async {
        let db = DB()
        let rows = [|
            { CargoID = 1; Currency = "EUR"; IsInternal = true; Amount = 123.12m};
            { CargoID = 1; Currency = "USD"; IsInternal = false; Amount = 145.89m};
        |]
        printfn "starting async seq"
        do! AsyncSeq.iterAsync action (db.loadSapPL rows) 
        printfn "async seq ended"
    } |> Async.StartImmediate
with
 | exc ->
     printfn "Error %s " (exc.ToString())

Все тоже хорошос точки зрения БД (я вижу ожидаемые записи в таблице), но я не могу прочитать сообщения ("*** Ok ... ") action в консоли F # Interactive в Visual Studio. Я также пробовал с AsyncSeq.iter вместо AsyncSeq.iterAsync и синхронной версией action. Что мне не хватает? Только "starting async seq" и "async seq ended" и журналирование sql (из тривиального SqlQueryEvent |> Event.add, не показанного выше) печатаются из выражения асинхронного вычисления.

1 Ответ

1 голос
/ 30 октября 2019

Мне пришлось использовать yield вместо return в моих asyncSeq функциях, чтобы очистить и вставить строки в таблицу.

let emptySapPl () =
    asyncSeq {
        try
            let! dels =   
                query {
                 for pl in context.OilPhysical.SapPl do 
                 where (true)
                } |> Seq.``delete all items from single table``
            yield Ok (dels, "deleted") // and not return OK ..
        with 
        | exc -> 
            yield Error (exc.Message, "emptySapPl failed") // and not return Error
    }

let loadSapPL (rows:RowSapPL[]) : AsyncSeq<Result<int * string, string * string>> = 
    asyncSeq {
        try
            rows
            |> Array.iter( fun r ->
                context.OilPhysical.SapPl.``Create(Amount, CargoID, Currency, InternalCurr)`` (r.Amount, r.CargoID, r.Currency, r.IsInternal) |> ignore
            )
            do! context.SubmitUpdatesAsync()
            yield Ok (rows |> Array.length, "inserted") // and not return OK ..
        with
        | exc ->
            yield Error (exc.Message, "loadSapPL failed") // and not return Error
    }

Но я немного разочарован тем, что получаюнет предупреждений / ошибок от компилятора ...

...