Как получить скрипт F # fsx для повторного выполнения и повторного извлечения данных SQL каждый раз, когда они вызываются из C #? - PullRequest
0 голосов
/ 05 декабря 2018

Я написал простое веб-приложение на C #, которое позволяет пользователю вводить некоторые данные, а затем по нажатию кнопки:

  1. данные сохраняются в локальную базу данных SQL
  2. anСценарий F # вызывается для извлечения этих данных с использованием SqlCommandProvider
  3. , когда данные передаются обратно в C #
  4. переданные данные используются в некоторых вычислениях
  5. результаты расчета отображаются наэкран веб-страницы

Все работает нормально, за исключением того, что при нажатии кнопки более одного раза те же данные отправляются обратно из F # с самого первого выполнения.

ЭтоПохоже, что сценарий не выполняется повторно, как ожидалось, но если это так, кажется, что SqlCommandProvider может быть заблокирован для первого набора результатов, которые он первоначально возвратил.

Очевидно, что отправлять его не нужноданные в БД и обратно, чтобы выполнить эти расчеты.Это приложение создается с целью демонстрации совместного использования F # / C # в решении, а не фактического эффективного использования приложения в производственных целях.

#I "../packages/FSharp.Data.3.0.0/lib/net45"
#r "FSharp.Data.dll"
open FSharp.Data

#I "../packages/FSharp.Data.SqlClient.2.0.1/lib/net40"
#r "FSharp.Data.SqlClient.dll"
open FSharp.Data.SqlClient

[<Literal>]
let ConnectionString = 
    @"server=(local); database=CostPriceCalc; user id=MyId; password=MyPassword;"

[<Literal>]
let SqlQuery = "SELECT SharesSold, PricePerShare, SellDate, CostMethod FROM [CalcInputs] WHERE Id = (SELECT MAX(Id) FROM [CalcInputs])"
let cmd = new SqlCommandProvider<SqlQuery, ConnectionString>(ConnectionString)
let result = cmd.Execute() |> Seq.toArray

Кроме того, я еще не обрабатываю данные, возвращаемые из F # должным образомвместо этого я очень неуклюже просто преобразовываю строку и анализирую ее, чтобы получить то, что мне нужно.Это, однако, кажется неактуальным (за исключением того, что это в корне неверно), потому что переменные C # очищаются каждый раз перед извлечением из F # и одни и те же данные продолжают возвращаться каждый раз из F #.

   public static List<NewData.Values> ParseFsharpData()
    {
        var parsedList = new List<NewData.Values>();
        foreach (var item in CalculateCostPrice.result)
        {
            var parsedData = item.ToString().Replace(";", ",").
                Replace("{ ", "").Replace(" }", "").Replace("Some ", "").
                Replace("M,", ",").Replace("\"", "").
                Split(',').ToList();
            parsedList = (from value in parsedData
                select new NewData.Values
                {
                    Value1 = value.Split('=')[0].Trim(),
                    Value2 = value.Split('=')[1].Trim()
                }).ToList();
        }
        return parsedList;
    }

Наконец, у меня естьподтвердил, что новые данные правильно записываются в БД.Проблема, по-видимому, связана либо с самим сценарием F # fsx (с именем CalculateCostPrice), который не выполняется повторно, как ожидалось, либо с SqlCommandProvider, кэширующим данные.

1 Ответ

0 голосов
/ 06 декабря 2018

Я еще не пытался скомпилировать сценарии .fsx, но мой опыт использования модулей в проектах F # заставляет меня думать, что:

let result = cmd.Execute() |> Seq.toArray

компилируется в статическую переменную класса CalculateCostPrice.Это будет означать, что он будет выполнен только один раз (при первом его использовании, если не раньше), а результат будет сохранен в переменной «result».

Добавление параметра типа «unit» должно изменитьсяэто метод (опять же, еще не проверенный):

let result() = cmd.Execute() |> Seq.toArray

И вы бы назвали его из C # как:

foreach (var item in CalculateCostPrice.result())

В этом случае выполнение произойдет, когда вы вызоветеметод, а не когда класс инициализируется.Я мог бы переименовать его из «result» в «executeQuery» или что-то в этом роде.

...