Oracle UDF Problem - Objekt geht auf gespeicherte Prozedur aber tut Einsatz NVARCHAR2, kein Einsatz für DECIMAL

StackOverflow https://stackoverflow.com/questions/4379121

Frage

Wir haben eine Tabelle wie:

CREATE TABLE ESIPARIS.T_ORDER_LINE

(
  NO           NUMBER(18),
  ORDER_NO     NUMBER(18),
  ITEM_NO      NVARCHAR2(15),
  AMOUNT       NUMBER(18,3),
  INSERT_DATE  DATE,
  INSERT_USER  NVARCHAR2(20),
  UPDATE_DATE  DATE,
  UPDATE_USER  NVARCHAR2(20),
  FLEXFIELD_1  NVARCHAR2(100),
  FLEXFIELD_2  NVARCHAR2(100),
  FLEXFIELD_3  NVARCHAR2(100),
  FLEXFIELD_4  NVARCHAR2(100)
)
TABLESPACE DEVEL
PCTUSED    0
PCTFREE    10
INITRANS   1
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             1M
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
NOLOGGING 
NOCOMPRESS 
NOCACHE
NOPARALLEL
MONITORING;

Und Objekte wie:

DROP TYPE ESIPARIS.ORDER_LINE_ROW;

CREATE OR REPLACE TYPE ESIPARIS.ORDER_LINE_ROW AS OBJECT
(
NO           NUMBER(18),
ORDER_NO     NUMBER(18),
ITEM_NO      NVARCHAR2(15),
AMOUNT       NUMBER(18,3),
INSERT_DATE  DATE,
INSERT_USER  NVARCHAR2(20),
UPDATE_DATE  DATE,
UPDATE_USER  NVARCHAR2(20),
FLEXFIELD_1  NVARCHAR2(100),
FLEXFIELD_2  NVARCHAR2(100),
FLEXFIELD_3  NVARCHAR2(100),
FLEXFIELD_4  NVARCHAR2(100)
)
/

CREATE OR REPLACE TYPE ESIPARIS.ORDER_LINE_TABLE as table of ESIPARIS.ORDER_LINE_ROW;
/

Und eine gespeicherte Prozedur Handle-Objekte von einer .NET-Anwendung zu Einfügungen gesendet:

CREATE OR REPLACE PROCEDURE ESIPARIS.pr_getorder_line (
   deneme   IN   order_line_table
)
IS
   err_code   NVARCHAR2 (500) := '';
   err_msg    NVARCHAR2 (500) := '';
BEGIN
   FOR i IN 1 .. deneme.COUNT
   LOOP
      INSERT INTO t_order_line
                  (NO, order_no, item_no,
                   amount, insert_date,
                   insert_user, update_date,
                   update_user, flexfield_1,
                   flexfield_2, flexfield_3,
                   flexfield_4
                  )
           VALUES (deneme (i).NO, deneme (i).order_no, nvl(deneme (i).item_no,'null geldi'),
                   nvl(deneme (i).amount,5363377869), deneme (i).insert_date,
                   deneme (i).insert_user, deneme (i).update_date,
                   deneme (i).update_user, deneme (i).flexfield_1,
                   deneme (i).flexfield_2, deneme (i).flexfield_3,
                   deneme (i).flexfield_4
                  );
   END LOOP;

   COMMIT;
EXCEPTION
   WHEN OTHERS
   THEN
      err_code := SQLCODE;
      err_msg := SUBSTR (SQLERRM, 1, 200);

      INSERT INTO esiparis.t_error_log
                  (event_date, event_object, MESSAGE
                  )
           VALUES (SYSDATE, err_code, err_msg
                  );
END;
/

Wir haben UDT Klassen in .NET 4.0 das Visual Studio 2010 und die ODP.NET Plugin. Wir sind an einem Punkt, dass die Werte von einer NET-Anwendung gesendet, die in NVARCHAR2 Datentyp sind, eingesetzt sind. Daten in NUMBER oder DATE-Datentypen können nicht eingefügt werden. Irgendwelche Ideen?

War es hilfreich?

Lösung

Ihr Problem ist wahrscheinlich durch Umwandlung von nativen .NET-Typen geben (int, double, Datetime, etc.) in Ihrem Aufruf C # -Code zu den Oracle-Typen verwendet (Nummer, Datum), um die Werte in der Datenbank zu speichern. Sicherstellen, dass die UDT-Klassen verwenden Oracle-Typen, nicht .NET-Typen.

Auch wenn alles, was Sie tun Iterieren über Ihre Sammlung ist die Datensätze einzufügen, sollten Sie die Verwendung von Oracle Bulk-Bindungsfähigkeiten berücksichtigen, da es wesentlich effizienter sein wird. Siehe http://dotnetslackers.com/articles/ado_net/BulkOperationsUsingOracleDataProviderForNETODPNET.aspx für einen guten Beispiel.

EDIT: Per Ihre commment: „Wir waren auf der Suche nach einem direkten SP Beispiel Dieses gut war Bind-Variablen für die Verwendung..“

So oder so, müssen Sie richtig die Typen von .NET Oracle konvertieren werden. Es klingt wie Sie tun genau das, was in diesem Dokument ist: http://download.oracle.com/docs/html/E15167_01/featUDTs htm # CJAGFHBA

EDIT2: Basierend auf dem Code in der Antwort, die Sie selbst geschrieben, es sieht aus wie ein es (etwas) besser Weg, um dies zu beheben.

Sie kommentiert sich einige Zeilen wie diese:

//[07.12.2010]ISMAILH : ISNULLS ARE COMMENTED OUT FOR PROPER WORKING!
// TODO : Add code to initialise the object
//this.m_AMOUNTIsNull = true;

Der Zweck m_AMOUNTIsNull (oder die Eigenschaft AMOUNTIsNull, die dieses Feld verwendet) ist der Code zu ermöglichen, einen tatsächlichen m_AMOUNT Wert zu unterscheiden, die festgelegt ist und eine, die, weil der Standard .NET-Wert (0 für ein dezimal) gesetzt ist verwendet wird.

Das ist, warum der Wert vor dem UDT geprüft wird, wird mit dem m_AMOUNT Wert gefüllt:

if ((AMOUNTIsNull == false)) {
    Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "AMOUNT", this.AMOUNT);

Wenn die UDT aus der Datenbank abgerufen werden, wird AMOUNTIsNull gesetzt basierend darauf, ob das Datenbankfeld ist null:

this.AMOUNTIsNull = Oracle.DataAccess.Types.OracleUdt.IsDBNull(con, pUdt, "AMOUNT");
if ((AMOUNTIsNull == false)) {
    this.AMOUNT = ((decimal)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "AMOUNT")));
}

Aber wenn Sie Ihr .NET-Objekt verwenden und die Einstellung der AMOUNT Eigenschaft, nicht AMOUNTIsNull nicht verändert bekommen:

[OracleObjectMappingAttribute("AMOUNT")]
public decimal AMOUNT {
    get {
        return this.m_AMOUNT;
    }
    set {
        this.m_AMOUNT = value;
    }
}

Wenn Sie es ändern, damit es richtig eingestellt ist (und lösen Sie die kommentierten-out Fix Sie bereits gemacht haben), werden Sie ab, da Sie besser sind in der Lage sowohl Speicher einen Wert und einen Nullwert darstellen und :

[OracleObjectMappingAttribute("AMOUNT")]
public decimal AMOUNT {
    get {
        return this.m_AMOUNT;
    }
    set {
        this.AMOUNTIsNull = false;
        this.m_AMOUNT = value;
    }
}

Andere Tipps

Nachdem die automatisch generierten Klassen von der Oracle ODP.NET Visual Studio Plugin Check-out, unsere .NET-Entwickler herausgefunden hat, dass es funktioniert normalerweise nach ein paar Zeilen in den automatisch generierten Code zu kommentieren heraus, 4 Zeilen nach der Zeile, die

"// [07.12.2010] ISMAILH: ISNULLS SIND FÜR DIE RICHTIGE ARBEITS COMMENTED OUT".

Danach alles richtig funktionierte, aber ich frage mich, über den tieferen Grund dafür. Warum hat erzeugt das Plugin diese Zeilen an erster Stelle? :

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.1
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace ESiparis {
    using System;
    using Oracle.DataAccess.Client;
    using Oracle.DataAccess.Types;
    using System.Xml.Serialization;
    using System.Xml.Schema;

    public class ORDER_LINE_ROW : INullable, IOracleCustomType, IXmlSerializable,IDisposable {

        private bool m_IsNull;
        private decimal m_AMOUNT;
        private bool m_AMOUNTIsNull;
        private System.DateTime m_UPDATE_DATE;
        private bool m_UPDATE_DATEIsNull;
        private string m_FLEXFIELD_1;
        private System.DateTime m_INSERT_DATE;
        private bool m_INSERT_DATEIsNull;
        private string m_FLEXFIELD_3;
        private string m_UPDATE_USER;
        private string m_FLEXFIELD_2;
        private decimal m_ORDER_NO;
        private bool m_ORDER_NOIsNull;
        private string m_FLEXFIELD_4;
        private string m_INSERT_USER;
        private decimal m_NO;
        private bool m_NOIsNull;
        private string m_ITEM_NO;

        public ORDER_LINE_ROW() {
            //[07.12.2010]ISMAILH : ISNULLS ARE COMMENTED OUT FOR PROPER WORKING!
            // TODO : Add code to initialise the object
            //this.m_AMOUNTIsNull = true;
            //this.m_UPDATE_DATEIsNull = true;
            //this.m_INSERT_DATEIsNull = true;
            //this.m_ORDER_NOIsNull = true;
            Dispose(false);
            this.m_NOIsNull = true;
        }

        public ORDER_LINE_ROW(string str) {
            // TODO : Add code to initialise the object based on the given string
            Dispose(false);
        }

        public virtual bool IsNull {
            get {
                return this.m_IsNull;
            }
        }

        public static ORDER_LINE_ROW Null {
            get {
                ORDER_LINE_ROW obj = new ORDER_LINE_ROW();
                obj.m_IsNull = true;
                return obj;
            }
        }

        [OracleObjectMappingAttribute("AMOUNT")]
        public decimal AMOUNT {
            get {
                return this.m_AMOUNT;
            }
            set {
                this.m_AMOUNT = value;
            }
        }

        public bool AMOUNTIsNull {
            get {
                return this.m_AMOUNTIsNull;
            }
            set {
                this.m_AMOUNTIsNull = value;
            }
        }

        [OracleObjectMappingAttribute("UPDATE_DATE")]
        public System.DateTime UPDATE_DATE {
            get {
                return this.m_UPDATE_DATE;
            }
            set {
                this.m_UPDATE_DATE = value;
            }
        }

        public bool UPDATE_DATEIsNull {
            get {
                return this.m_UPDATE_DATEIsNull;
            }
            set {
                this.m_UPDATE_DATEIsNull = value;
            }
        }

        [OracleObjectMappingAttribute("FLEXFIELD_1")]
        public string FLEXFIELD_1 {
            get {
                return this.m_FLEXFIELD_1;
            }
            set {
                this.m_FLEXFIELD_1 = value;
            }
        }

        [OracleObjectMappingAttribute("INSERT_DATE")]
        public System.DateTime INSERT_DATE {
            get {
                return this.m_INSERT_DATE;
            }
            set {
                this.m_INSERT_DATE = value;
            }
        }

        public bool INSERT_DATEIsNull {
            get {
                return this.m_INSERT_DATEIsNull;
            }
            set {
                this.m_INSERT_DATEIsNull = value;
            }
        }

        [OracleObjectMappingAttribute("FLEXFIELD_3")]
        public string FLEXFIELD_3 {
            get {
                return this.m_FLEXFIELD_3;
            }
            set {
                this.m_FLEXFIELD_3 = value;
            }
        }

        [OracleObjectMappingAttribute("UPDATE_USER")]
        public string UPDATE_USER {
            get {
                return this.m_UPDATE_USER;
            }
            set {
                this.m_UPDATE_USER = value;
            }
        }

        [OracleObjectMappingAttribute("FLEXFIELD_2")]
        public string FLEXFIELD_2 {
            get {
                return this.m_FLEXFIELD_2;
            }
            set {
                this.m_FLEXFIELD_2 = value;
            }
        }

        [OracleObjectMappingAttribute("ORDER_NO")]
        public decimal ORDER_NO {
            get {
                return this.m_ORDER_NO;
            }
            set {
                this.m_ORDER_NO = value;
            }
        }

        public bool ORDER_NOIsNull {
            get {
                return this.m_ORDER_NOIsNull;
            }
            set {
                this.m_ORDER_NOIsNull = value;
            }
        }

        [OracleObjectMappingAttribute("FLEXFIELD_4")]
        public string FLEXFIELD_4 {
            get {
                return this.m_FLEXFIELD_4;
            }
            set {
                this.m_FLEXFIELD_4 = value;
            }
        }

        [OracleObjectMappingAttribute("INSERT_USER")]
        public string INSERT_USER {
            get {
                return this.m_INSERT_USER;
            }
            set {
                this.m_INSERT_USER = value;
            }
        }

        [OracleObjectMappingAttribute("NO")]
        public decimal NO {
            get {
                return this.m_NO;
            }
            set {
                this.m_NO = value;
            }
        }

        public bool NOIsNull {
            get {
                return this.m_NOIsNull;
            }
            set {
                this.m_NOIsNull = value;
            }
        }

        [OracleObjectMappingAttribute("ITEM_NO")]
        public string ITEM_NO {
            get {
                return this.m_ITEM_NO;
            }
            set {
                this.m_ITEM_NO = value;
            }
        }

        public virtual void FromCustomObject(Oracle.DataAccess.Client.OracleConnection con, System.IntPtr pUdt) {
            if ((AMOUNTIsNull == false)) {
                Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "AMOUNT", this.AMOUNT);
            }
            if ((UPDATE_DATEIsNull == false)) {
                Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "UPDATE_DATE", this.UPDATE_DATE);
            }
            Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "FLEXFIELD_1", this.FLEXFIELD_1);
            if ((INSERT_DATEIsNull == false)) {
                Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "INSERT_DATE", this.INSERT_DATE);
            }
            Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "FLEXFIELD_3", this.FLEXFIELD_3);
            Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "UPDATE_USER", this.UPDATE_USER);
            Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "FLEXFIELD_2", this.FLEXFIELD_2);
            if ((ORDER_NOIsNull == false)) {
                Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "ORDER_NO", this.ORDER_NO);
            }
            Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "FLEXFIELD_4", this.FLEXFIELD_4);
            Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "INSERT_USER", this.INSERT_USER);
            if ((NOIsNull == false)) {
                Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "NO", this.NO);
            }
            Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "ITEM_NO", this.ITEM_NO);
        }

        public virtual void ToCustomObject(Oracle.DataAccess.Client.OracleConnection con, System.IntPtr pUdt) {
            this.AMOUNTIsNull = Oracle.DataAccess.Types.OracleUdt.IsDBNull(con, pUdt, "AMOUNT");
            if ((AMOUNTIsNull == false)) {
                this.AMOUNT = ((decimal)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "AMOUNT")));
            }
            this.UPDATE_DATEIsNull = Oracle.DataAccess.Types.OracleUdt.IsDBNull(con, pUdt, "UPDATE_DATE");
            if ((UPDATE_DATEIsNull == false)) {
                this.UPDATE_DATE = ((System.DateTime)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "UPDATE_DATE")));
            }
            this.FLEXFIELD_1 = ((string)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "FLEXFIELD_1")));
            this.INSERT_DATEIsNull = Oracle.DataAccess.Types.OracleUdt.IsDBNull(con, pUdt, "INSERT_DATE");
            if ((INSERT_DATEIsNull == false)) {
                this.INSERT_DATE = ((System.DateTime)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "INSERT_DATE")));
            }
            this.FLEXFIELD_3 = ((string)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "FLEXFIELD_3")));
            this.UPDATE_USER = ((string)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "UPDATE_USER")));
            this.FLEXFIELD_2 = ((string)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "FLEXFIELD_2")));
            this.ORDER_NOIsNull = Oracle.DataAccess.Types.OracleUdt.IsDBNull(con, pUdt, "ORDER_NO");
            if ((ORDER_NOIsNull == false)) {
                this.ORDER_NO = ((decimal)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "ORDER_NO")));
            }
            this.FLEXFIELD_4 = ((string)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "FLEXFIELD_4")));
            this.INSERT_USER = ((string)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "INSERT_USER")));
            this.NOIsNull = Oracle.DataAccess.Types.OracleUdt.IsDBNull(con, pUdt, "NO");
            if ((NOIsNull == false)) {
                this.NO = ((decimal)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "NO")));
            }
            this.ITEM_NO = ((string)(Oracle.DataAccess.Types.OracleUdt.GetValue(con, pUdt, "ITEM_NO")));
        }

        public virtual void ReadXml(System.Xml.XmlReader reader) {
            // TODO : Read Serialized Xml Data
        }

        public virtual void WriteXml(System.Xml.XmlWriter writer) {
            // TODO : Serialize object to xml data
        }

        public virtual XmlSchema GetSchema() {
            // TODO : Implement GetSchema
            return null;
        }

        public override string ToString() {
            // TODO : Return a string that represents the current object
            return "";
        }

        public static ORDER_LINE_ROW Parse(string str) {
            // TODO : Add code needed to parse the string and get the object represented by the string
            return new ORDER_LINE_ROW();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool p)
        {
            if (p == true)
            {
                GC.SuppressFinalize(this);
            }
        }
    }

    // Factory to create an object for the above class
    [OracleCustomTypeMappingAttribute("ESIPARIS.ORDER_LINE_ROW")]
    public class ORDER_LINE_ROWFactory : IOracleCustomTypeFactory ,IDisposable {

        public virtual IOracleCustomType CreateObject() {
            ORDER_LINE_ROW obj = new ORDER_LINE_ROW();
            return obj;
        }

        public void Dispose()
        {

        }
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top