Не удается получить значение при использовании OleDbParameter

Это не очень хорошая форма для создания запроса, как

let fnam_query =
    "select * from file_name_info where fnam_origin = 'invoice_cloud'"

Но блок кода ниже имеет две проблемы. Во-первых, fnam_readOk возвращает false из чтения.

Во-вторых, как можно избавиться от OleDbParameter? Я пытался с помощью use, но получил ошибку во время компиляции, говоря OleDbType.Char не может быть использовано внутри использования.

let fnam_query = 
    "select * from file_name_info where fnam_origin = '?' "

use fnam_cmd = new OleDbCommand(fnam_query, db_con)
let local_params = new OleDbParameter("fnam_origin", OleDbType.Char)
fnam_cmd.Parameters.Add(local_params) |> ignore

let fnam_reader = fnam_cmd.ExecuteReader ()
let fnam_readOK = fnam_reader.Read ()

let ic_lb_fnam =
    if fnam_readOK then
        fnam_reader.GetString(2)
    else
        "ic_lockbox.txt" 

2 ответа

Решение

Есть много проблем с этим кодом. Одним из них является то, что вы использовали OleDbParameter перегрузка, которая передает имя и значение. Линия new OleDbParameter("fnam_origin", OleDbType.Char) указывает параметр с именем fnam_origin и целочисленное значение, равное любому значению, лежащему в основе OleDbType.Char является.

Другая проблема заключается в том, что вы вообще не используете этот параметр. '?' это просто строка, которая содержит ?,

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

Ваш запрос должен быть:

let fnam_query = 
"select * from file_name_info where fnam_origin = ? "

Вы также должны использовать правильный тип параметра. Char используется только для параметров фиксированной длины. Вы должны использовать VarChar или даже лучше, NVarchar.

Наконец, вы должны передать значение параметра, которое вы хотите. Ваш код вообще не указывает значение параметра.

Вся функция должна выглядеть так:

let fnam_query =  "select * from file_name_info where fnam_origin = ? "
use db_con = new OleDbConnection("...")
use fnam_cmd = new OleDbCommand(fnam_query, db_con)
let local_params = new OleDbParameter("origin", SqlDbType.NVarChar,100)
fnam_cmd.Parameters.Add(local_params) |> ignore
local_params.Value <- "GR"


db_con.Open()
let fnam_reader = fnam_cmd.ExecuteReader ()
let fnam_readOK = fnam_reader.Read ()
...

Тем не менее, лучшая реализация - создать команду один раз и повторно использовать ее с другими соединениями и значениями:

let build_cmd = 
    let fnam_query =  "select * from file_name_info where fnam_origin = ? "
    let fnam_cmd = new OleDbCommand(fnam_query)
    let local_params = new OleDbParameter("whatever", SqlDbType.NVarChar,100)
    fnam_cmd.Parameters.Add(local_params) |> ignore
    fnam_cmd



use db_con = new OleDbConnection("...")
build_cmd.Connection <- db_con
build_cmd.Parameters.[0].Value <- "GR"
db_con.Open()

Основываясь на превосходном ответе, который я получил от Panagiotis Kanavos, я изменил другое место в моем коде, где мне нужны параметры, которые не были встроены в строку запроса. Я решил использовать cmd.Parameters.Add а не иметь отдельный OleDbParameter вал.

(* by looking at the xfer_type, really the arg passed to main, 
we can determine the report type parameter for the Access 
database. *)
let select_report_type xfer_type =
    match xfer_type with
    | "/al" -> 0
    | "/am" -> 1
    | "/ap" -> 2
    | "/pm" -> 3
    | "/pp" -> 4
    | _     -> 99

let query = "select count(*) from ProcessStatus where ReportType = ? and ReportDate = ? and ReportFileName = ? "
use cmd = new OleDbCommand(query , db_con)
cmd.Parameters.Add(new OleDbParameter("ReportType",(OleDbType.VarChar,5))) |> ignore
cmd.Parameters.[0].Value <- ((select_report_type xfer_type).ToString())

cmd.Parameters.Add(new OleDbParameter("ReportDate",OleDbType.VarChar, 11)) |> ignore
cmd.Parameters.[1].Value <- report_date

cmd.Parameters.Add(new OleDbParameter("ReportFileName",OleDbType.VarChar, 100)) |> ignore
cmd.Parameters.[2].Value <- fn

let sql_reader = cmd.ExecuteReader ()
        if (sql_reader.Read ()) then
Другие вопросы по тегам