0 Replies Latest reply: Apr 1, 2012 8:58 PM by 927805 RSS

    ODAC OracleDataAdapter で RETURING句を動作させる方法

    927805
      INSERT時にキーをOracle シーケンスで設定し、そのキー値を RETURNING句で取得しDataTableに自動で
      設定することを目的とし、次のマイクロソフトの見本プログラムを実際実行してみたのですが、
      (見本プログラムurl)
      http://msdn.microsoft.com/ja-jp/library/bb399230.aspx
      Update()のところで
      型 'Oracle.DataAccess.Types.OracleDecimal' のオブジェクトを型 'System.IConvertible' にキャストできません。列 ID に <null> を格納できませんでした。 必要な型は Int32 です。
      のエラーが発生してうまく実行出来ません。

      .NET 環境で、Oracle シーケンスとRETURNING句を利用し、もしくは別の方法で、
      SQLServerのIdentityと同等の機能を実現したいと思っています。
      (INSERT後ID値がDataTableにも設定されている動作)

      一応、SequenceTest_Table は作成されており、IDには 100 - 145 が設定されており、
      SequenceTest_Sequence シーケンスも作成されており、INSERTにおいて機能しているようです。

      どのようにすれば、エラー回避できて目的を達成出来ますか。
      よろしくお願いします。

      実験環境:
       サーバー側:
        WindowsServer2003で動作
        Oracle     11g r2
       クライアント側:
        Windows7 Pro
        VisualStudio 2010
        ODAC 112030

      見本コードの修正部分と実際のコードを示します。
      修正部分:
      1.参照設定でOracle.DataAccess Ver 4.11.2.3.0 追加
      2.using Oracle.DataAccess.Client ;     // 追加記述
      using Oracle.DataAccess.Types ;          // 追加記述
        を追加
      3.varchar 部分を varchar2 に変更
      4.OracleType 部分を OracleDbType に変更

      using Oracle.DataAccess.Client ;     // 追加記述
      using Oracle.DataAccess.Types ;          // 追加記述

      public void OracleSequence(String connectionString)
      {   String insertString =
      "INSERT INTO SequenceTest_Table (ID, OtherColumn)" +
      "VALUES (SequenceTest_Sequence.NEXTVAL, :OtherColumn)" +
      "RETURNING ID INTO :ID";
      using (OracleConnection conn = new OracleConnection(connectionString))
      {  //Open a connection.
      conn.Open();
      OracleCommand cmd = conn.CreateCommand();
      // Prepare the database.
      cmd.CommandText = "DROP SEQUENCE SequenceTest_Sequence";
      try { cmd.ExecuteNonQuery(); } catch { }
      cmd.CommandText = "DROP TABLE SequenceTest_Table";
      try { cmd.ExecuteNonQuery(); } catch { }

           // 下記に修正 cmd.CommandText = "CREATE TABLE SequenceTest_Table " + "(ID int PRIMARY KEY, OtherColumn varchar(255))";
           // ちなみに、 int PRIMARY の部分を number(5) PRIMARY に変更しても int と同様の現象
      cmd.CommandText = "CREATE TABLE SequenceTest_Table " + "(ID int PRIMARY KEY, OtherColumn varchar2(255))";
      //cmd.CommandText = "CREATE TABLE SequenceTest_Table " + "(ID number(5) PRIMARY KEY, OtherColumn varchar2(255))";

      cmd.ExecuteNonQuery();
      cmd.CommandText = "CREATE SEQUENCE SequenceTest_Sequence " +
      "START WITH 100 INCREMENT BY 5";
      cmd.ExecuteNonQuery();
      DataTable testTable = new DataTable();
      DataColumn column = testTable.Columns.Add("ID", typeof(int));
      column.AutoIncrement = true;
      column.AutoIncrementSeed = -1;
      column.AutoIncrementStep = -1;
      testTable.PrimaryKey = new DataColumn[] { column };
      testTable.Columns.Add("OtherColumn", typeof(string));
      for (int rowCounter = 1; rowCounter <= 15; rowCounter++)
      {
      testTable.Rows.Add(null, "Row #" + rowCounter.ToString());
      }

      Console.WriteLine("Before Update => ");
      foreach (DataRow row in testTable.Rows)
      {
      Console.WriteLine(" {0} - {1}", row["ID"], row["OtherColumn"]);
      }
      Console.WriteLine();

      cmd.CommandText =
      "SELECT ID, OtherColumn FROM SequenceTest_Table";
      OracleDataAdapter da = new OracleDataAdapter(cmd);
      da.InsertCommand = new OracleCommand(insertString, conn);

      // 下記に修正     da.InsertCommand.Parameters.Add(":ID", OracleType.Int32, 0, "ID");
      da.InsertCommand.Parameters.Add(":ID", OracleDbType.Int32, 0, "ID");

      da.InsertCommand.Parameters[0].Direction = ParameterDirection.Output;
      /* ちなみに、Direction = ParameterDirection.Input とすればエラーなく終了するが、
           After Updateで表示の IDはマイナス値(-1から-15)となり100から170とならず目的を達成しない。
           da.InsertCommand.Parameters[0].Direction = ParameterDirection.Input ;
           */

      // 下記に修正 da.InsertCommand.Parameters.Add(":OtherColumn", OracleType.VarChar, 255, "OtherColumn");
      da.InsertCommand.Parameters.Add(":OtherColumn", OracleDbType.Varchar2, 255, "OtherColumn");

      da.InsertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
      da.UpdateBatchSize = 10;
      da.Update(testTable); // ここでエラー発生
      Console.WriteLine("After Update => ");
      foreach (DataRow row in testTable.Rows)
      {
      Console.WriteLine(" {0} - {1}", row["ID"], row["OtherColumn"]);
      }
      // Close the connection.
      conn.Close();
      }
      }