何时是String而不是String

时间:2012-03-16 22:16:44

标签: c# oracle sequence

来自“数据库引擎中出现问题”部门:

此函数返回看似有效值的内容,但未发布记录(无错误消息):

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工作(返回一个值,插入是(貌似)没有嘎嘎叫)...但是,没有记录插入到数据库中。

这个kludgy(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();
        }

更新redux:

卢克对使用两个同时连接提出了一个很好的观点;所以,我把代码更改为:

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;
    }
}

......但是在Mudville仍然没有快乐。

重新访问REDx:

我得到了它的工作;感谢大家的帮助和见解。

实际上,它已经工作了一段时间 - 我在Toad中的愚蠢查询是问题 - 我忘了我在新记录中添加的值与我查询时的值略有不同...所以看起来记录不是被添加,但他们真的。 TGIF!

2 个答案:

答案 0 :(得分:1)

你设置参数的方式似乎很奇怪,因为你的参数对象最终没有名字 - 尝试改变你的代码类似于:

OracleParameter p_TICKETID = new OracleParameter("p_TICKETID", OracleDbType.NVarchar2, ParameterDirection.Input);
p_TICKETID.Size = 20;

答案 1 :(得分:1)

我尝试在上面运行你的代码,如果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
-------
#######

我在TICKETID列上放置了PK约束,在运行代码两次后,我遇到了约束违规错误。

修改

在回复您的评论时,可以使用触发器填充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;
/