Когда Строка не Строка - PullRequest
1 голос
/ 17 марта 2012

Из отдела «Вещи, попадающие в ядро ​​базы данных»:

Эта функция возвращает то, что выглядит как допустимое значение, но запись не опубликована (нет сообщения об ошибке):

private String GetInterpreterTicketIDSequenceVal()
{
    con = new OracleConnection(oradb);
    con.Open();

    String query = "SELECT TO_CHAR(SYSDATE,'YYYYMMDD-') || LTRIM(TO_CHAR(ABC.SOMETABLEID.NEXTVAL, '000000')) FROM DUAL";

    cmd = new OracleCommand(query, con);
    cmd.CommandType = CommandType.Text;
    //MessageBox.Show(cmd.ExecuteScalar().ToString());
    return cmd.ExecuteScalar().ToString();
}

... SEEMS для работы (возвращает значение, и вставка выполняется (по-видимому) без криков) ... пока в базу данных не вставлена ​​запись.

Эта клуджая (sp?) Функция, OTOH:

private String GetSomeTableIDSequenceVal_Fake()
{
    int iYear = DateTime.Now.Year;
    int iMonth = DateTime.Now.Month;
    int iDay = DateTime.Now.Day;
    int iHour = DateTime.Now.Hour;
    int iSecond = DateTime.Now.Second;

    String sYear = iYear.ToString();
    String sMonth = iMonth.ToString();
    String sDay = iDay.ToString();
    String sHour = iHour.ToString();
    String sSecond = iSecond.ToString();

    if (iMonth < 10)
    {
        sMonth = String.Format("0{0}", sMonth);
    }
    if (iDay < 10)
    {
        sDay = String.Format("0{0}", sDay);
    }
    if (iHour < 10)
    {
        sHour = String.Format("0{0}", sHour);
    }
    if (iSecond < 10)
    {
        sSecond = String.Format("0{0}", sSecond);
    }

    return String.Format("{0}{1}{2}-{3}{4}", sYear, sMonth, sDay, sHour, sSecond);
}

... работает нормально - запись вставляется в базу данных (код, вызывающий эти функции, следует).

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

В любом случае, вот код, который вызывает любую из этих функций в контексте:

        try
        {
            con = new OracleConnection(oradb);
            con.Open();
            String query = "INSERT INTO ABC.SOMETABLE (TICKETID, TICKETSOURCE, ABOUTSOMEID, CATEGORYID, CONTACTEMAIL) VALUES (:p_TICKETID, :p_TICKETSOURCE, :p_ABOUTSOMEID, :p_CATEGORYID, :p_CONTACTEMAIL)";

            cmd = new OracleCommand(query, con);
            cmd.CommandType = CommandType.Text;

            // Params = TICKETID, TICKETSOURCE, ABOUTSOMEID, CATEGORYID, CONTACTEMAIL
            OracleParameter p_TICKETID = new OracleParameter();
            p_TICKETID.Direction = ParameterDirection.Input;
            p_TICKETID.OracleDbType = OracleDbType.NVarchar2;
            p_TICKETID.Size = 20;
            // This doesn't allow the record to be inserted...???
            //p_TICKETID.Value = GetSomeTableIDSequenceVal();
            // ...but when I "fake it" below, the record IS inserted
            //p_TICKETID.Value = GetSomeTableIDSequenceVal_Fake();                cmd.Parameters.Add(p_TICKETID);

            OracleParameter p_TICKETSOURCE = new OracleParameter();
            p_TICKETSOURCE.Direction = ParameterDirection.Input;
            p_TICKETSOURCE.OracleDbType = OracleDbType.NVarchar2;
            p_TICKETSOURCE.Size = 20;
            p_TICKETSOURCE.Value = textBoxTicketSource.Text;
            cmd.Parameters.Add(p_TICKETSOURCE);

            OracleParameter p_ABOUTSOMEID = new OracleParameter();
            p_ABOUTSOMEID.Direction = ParameterDirection.Input;
            p_ABOUTSOMEID.OracleDbType = OracleDbType.Int32;
            p_ABOUTSOMEID.Value = textBoxAboutSOMEID.Text;
            cmd.Parameters.Add(p_ABOUTSOMEID);

            OracleParameter p_CATEGORYID = new OracleParameter();
            p_CATEGORYID.Direction = ParameterDirection.Input;
            p_CATEGORYID.OracleDbType = OracleDbType.Int32;
            p_CATEGORYID.Value = textBoxCategoryID.Text;
            cmd.Parameters.Add(p_CATEGORYID);

            OracleParameter p_CONTACTEMAIL = new OracleParameter();
            p_CONTACTEMAIL.Direction = ParameterDirection.Input;
            p_CONTACTEMAIL.OracleDbType = OracleDbType.NVarchar2;
            p_CONTACTEMAIL.Size = 100;
            p_CONTACTEMAIL.Value = textBoxContactEmail.Text;
            cmd.Parameters.Add(p_CONTACTEMAIL);

            try
            {
                cmd.ExecuteNonQuery();
            }
            catch (OracleException ex)
            {
                MessageBox.Show(ex.Message);
            }
            MessageBox.Show("Apparent success");
        }
        finally
        {
            con.Close();
            con.Dispose();
        }

Обновление:

Я добавил поддержку Xaction, и, похоже, ничего не изменилось:

Я заключил его в транзакцию, и это не имеет значения:

  OracleTransaction ot;
        . . .
        try
        {
            ot = con.BeginTransaction();
            cmd.Transaction = ot;
            cmd.ExecuteNonQuery();
            ot.Commit();
        }
        catch (Exception ex)
        {
            ot.Rollback();
        }

Обновление редукса:

Люк сделал хороший вывод об использовании двух одновременных соединений; Итак, я изменил этот код на это:

private String GetInterpreterTicketIDSequenceVal()
{
    String query = "SELECT TO_CHAR(SYSDATE,'YYYYMMDD-') || LTRIM(TO_CHAR(ABC.SOMETABLEID.NEXTVAL, '000000')) FROM DUAL";

    OracleCommand oc = new OracleCommand(query, con);
    oc.CommandType = CommandType.Text;
    String s = oc.ExecuteScalar().ToString();
    try
    {
        return s;
    }
    catch (OracleException ex)
    {
        MessageBox.Show(ex.Message);
        return string.Empty;
    }
}

... но все еще нет радости в Мудвилле.

Обновление редукса вновь:

Я получил это работает; спасибо всем за помощь и понимание.

На самом деле, это работало какое-то время - проблема заключалась в моем глупом запросе в Toad - я забыл, что я добавляю немного новое значение в новые записи, чем то, к чему я обращался ... так что похоже, что записи не были добавляются, но они действительно были. TGIF!

Ответы [ 2 ]

1 голос
/ 17 марта 2012

Я попытался запустить ваш код выше и смог воспроизвести проблемы с ним, только если последовательность INTERPRETERTICKETID вышла за пределы 999999. Если у вас возникли проблемы, то должно быть что-то, о чем вы нам не сказали. Например, как определяется ваша таблица INTERPRETERTICKET? Какие ограничения на это? Как определяется последовательность? Есть ли на столе триггеры?

Есть ли необходимость в вашем GetInterpreterTicketIDSequenceVal() методе использовать свое собственное соединение с базой данных? Разве он не может использовать то же соединение, что и остальная часть вашего кода?

Если ваша последовательность INTERPRETERTICKETID вышла за пределы 999999, то вызов TO_CHAR вернет строку хэшей:

SQL> select ltrim(to_char(999999, '000000')) from dual;

LTRIM(T
-------
999999

SQL> select ltrim(to_char(1000000, '000000')) from dual;

LTRIM(T
-------
#######

Я наложил ограничение PK на столбец TICKETID, и после запуска вашего кода дважды я получил ошибку нарушения ограничения.

EDIT

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

Я добавил следующий триггер и изменил код C #, чтобы он не пытался вставить значение для TICKETID. Я запускал код C # несколько раз, и он, кажется, работал.

CREATE OR REPLACE TRIGGER INTERPRETERTICKETS_BI
  BEFORE INSERT ON INTERPRETERTICKETS
  FOR EACH ROW
BEGIN
  SELECT TO_CHAR(SYSDATE,'YYYYMMDD-') || LTRIM(TO_CHAR(INTERPRETERTICKETID.NEXTVAL, '000000'))
    INTO :new.TICKETID
    FROM DUAL;
END;
/
1 голос
/ 17 марта 2012

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

OracleParameter p_TICKETID = new OracleParameter("p_TICKETID", OracleDbType.NVarchar2, ParameterDirection.Input);
p_TICKETID.Size = 20;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...