C# эквивалент подготовленного заявления Java

Я пытаюсь создать готовый оператор в C#.

По какой-то причине все, что я пробую, заканчивается исключением.

Это мой код сейчас:

using (OracleCommand cmd = new OracleCommand())
{
    cmd.Connection = conn;
    cmd.CommandType = CommandType.Text;

    cmd.CommandText = "insert into daily_cdr_logs " +
            "(message) " +
            "values " +
            "(:message)";

    cmd.Parameters.Add(:message, msg);
    //OracleDbType.Int32, postpaid_duration, ParameterDirection.Input);
    cmd.Prepare();
    cmd.ExecuteNonQuery();
}

Я получаю исключение: "Операция недействительна из-за текущего состояния объекта".

2 ответа

Типичное подготовленное Oracle заявление выглядит следующим образом.

(обратите внимание, что только определение в подготовленном утверждении имеет : двоеточие, и тот, в cmd.Parameters.AddWithValue звонить не надо)

String msg = "something here";

using (OracleConnection con = new OracleConnection(...insert connection params here...))
{
  con.Open();
  OracleCommand cmd = con.CreateCommand();
  cmd.CommandType = CommandType.Text;
  cmd.CommandText = @"
        insert into daily_cdr_logs
        (message) 
        values 
        (:message)";
  cmd.Parameters.AddWithValue("message", msg);
  cmd.ExecuteNonQuery();
}

Я бы предложил сделать это так:

//create a connection
string conString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionName"].ConnectionString;
OracleConnection con = new OracleConnection(conString);

//create SQL and insert parameters
OracleCommand cmd = new OracleCommand("insert into daily_cdr_logs (message) values (:_message)", con);
cmd.Parameters.Add(new OracleParameter("_message", msg));

    try
    {
        //if connection is closed, open it
        if (con.State == ConnectionState.Closed)
             con.Open();

             //execute query
             cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
         //do something with the error
    }
    finally
    {
         //if connection is open, close it
         if (con.State == ConnectionState.Open)
         con.Close();
    }

Я создал строку подключения в моем файле web.config, продемонстрированном здесь.

Во-первых, ваш код не будет компилироваться, потому что :messageне является допустимым идентификатором C#. Строка, добавляющая параметр, должна быть:

       cmd.Parameters.Add(":message", msg);

Во-вторых, эффективнее регистрировать параметры на этапе подготовки:

       par = cmd.CreateParameter();
par.ParameterName = ":message";
cmd.Parameters.Add( par ); 

и укажите значение при каждом вызове подготовленного запроса:

       cmd.Parameters[i].Value = message;

если вы следите за своими параметрами, и

       cmd.Parameters[":message"].Value = message;

если нет.

В-третьих Prepare()метод в ODP.NET ничего не делает. Он нужен только для удовлетворения интерфейса IDbCommand, который требует Prepare() метод. Весьма прискорбно, что хотя Oracle были реализованы подготовить функциональность родного JDBC - интерфейс, они не отказались от него в ADO.NET. С другой стороны, ODP.NET рекламируется для локального кеширования повторяющихся запросов, что должно немного помочь.

Что касается исключения, которое вы получаете, я думаю, что это не имеет ничего общего с .Prepare(). Попробуйте использовать тот же код без него и посмотрите, сохраняется ли исключение. Наиболее вероятная причина - ваше соединение не открыто, поэтому оно не будет работать независимо от .Prepare().

Другие вопросы по тегам