F # вставить список в SQL Server - PullRequest
4 голосов
/ 15 февраля 2012

Я застрял в данный момент, пытаясь выяснить способ вставки в SQL Server из F #.

У меня есть функция F #, которая перебирает все файлы в папке, следуя заданному пользователем шаблону.Затем я могу использовать возвращенные данные, чтобы поместить их в список или (в идеале) вставить в базу данных.

У меня уже есть работающая функция вставки в sql, которая работает правильно:

let execNonQuery conn s =
let comm = 
    new SqlCeCommand(s, conn)
try 
    comm.ExecuteNonQuery() |> ignore
with e ->
    printf "Error : %A\n" e

let string = "insert into MyTable (MyColumn) values ('test .. again')"
execNonQuery conn string; // works

Я пытаюсь заставить этот метод работать должным образом:

let rec getAllFiles dir pattern =
    seq { yield! Directory.EnumerateFiles(dir, pattern)
          for d in Directory.EnumerateDirectories(dir) do
              yield! getAllFiles d pattern }

let getApplications (dir : string) (extension : string) = 
    getAllFiles  dir extension
    //|> Seq.toList // If I need to create a list of returned values
    |> Seq.iter (fun s -> SQLInsertString s) // This does not work as it complains about the function not being of type unit

Если я использую только Seq.toList и вызываю функцию, как показано ниже, она работает:

getApplications "C:\Admin" "*.txt" // works

Другая вещь, которую я не понимаю, - как создать рабочую команду вставки, которая принимает строку для значения.Например:

let SQLInsertString s = "insert into MyTable (MyColumn) values (%s)" //does not work

Ответы [ 2 ]

5 голосов
/ 15 февраля 2012

Ты почти у цели.Проблема в том, что sqlInsertString возвращает string, что недопустимо в Seq.iter.

. То, что вы делаете с sqlInsertString, - это создание строки с использованием строковых форматов.Он прекрасно подходит для функции sprintf:

let sqlInsertString s = 
    sprintf "insert into MyTable (MyColumn) values (%s)" s

Теперь вы можете использовать execNonQuery для результатов sqlInsertString, чтобы фактически вставить данные в базу данных.Поскольку execNonQuery возвращает unit, его можно легко использовать в Seq.iter:

// Assuming conn is a global and already defined variable.
let getApplications (dir : string) (extension : string) = 
    getAllFiles  dir extension
    |> Seq.iter (fun s -> execNonQuery conn (sqlInsertString s))

Поскольку аннотации типов являются избыточными, ваш код можно переписать более идиоматическим образом:

let getApplications dir extension conn = 
    getAllFiles dir extension
    |> Seq.iter (sqlInsertString >> execNonQuery conn)
4 голосов
/ 15 февраля 2012

Лучший способ передать параметры в запрос - использовать SqlCeParameter.Это проще, чем составление строк (потому что вам не нужно кодировать строки и экранирующие кавычки), и это также более безопасно, потому что вы избегаете SQL-инъекций .Вот базовый пример:

let sqlInsertString value = 
  // Create and open connection ('use' makes sure it gets closed at the end)
  use conn = new SqlCeConnection("...");
  conn.Open()
  // Create a command with a parameter named '@str'
  let cmd = new SqlCeCommand("INSERT INTO MyTable (MyColumn) values (@str)", conn)
  // Create parameter '@str' with string value 'value' and add it to the command
  let param = new SqlCeParameter("@str", SqlDbType.NVarChar, value)
  cmd.Parameters.Add(param)
  // Now run the command (exception handling omitted)
  cmd.ExecuteNonQuery() |> ignore

Используя эту функцию, теперь вы сможете использовать Seq.iter.Функция принимает string для вставки и возвращает unit (без значения), поэтому она может быть передана в Seq.iter:

let getApplications (dir : string) (extension : string) =  
  getAllFiles  dir extension 
  |> Seq.iter (fun s -> sqlInsertString s)

В качестве альтернативы, вы можете написать последнюю строку как |> Seq.iter sqlInsertString.Если вы сделаете это, вы в основном говорите, что аргумент s должен быть напрямую передан в функцию sqlInsertString.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...