Oracle UDF問題 - オブジェクトはストアドプロシージャに渡されますが、nvarchar2を挿入します。
-
09-10-2019 - |
質問
テーブルがあります:
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;
およびオブジェクトとして:
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;
/
.NETアプリケーションによって送信されたオブジェクトを処理するストアドプロシージャは、行を挿入します。
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;
/
作成しました udt Visual Studio 2010とTheを使用した.NET 4.0のクラス ODP.NET プラグイン。 NVarChar2データ型にある.NETアプリケーションによって送信される値が挿入されています。数または日付のデータ型のデータを挿入できません。何か案は?
解決
あなたの問題は、おそらく、データベースに値を保存するために使用されるOracleタイプ(数、日付)への呼び出しC#コードのネイティブ.NETタイプ(int、double、datetimeなど)からのタイプ変換によるものです。 UDTクラスが.NETタイプではなくOracleタイプを使用していることを確認してください。
また、レコードを挿入するためにコレクションを繰り返している場合は、Oracleのバルクバインディング機能がはるかに効率的であることを検討する必要があります。見る http://dotnetslackers.com/articles/ado_net/bulkoperationsususingoracledataproviderfornetodpnet.aspx 良い例として。
編集:Commment:「私たちは直接的なSPの例を探していました。これはバインド変数を使用するのに適していました。」
いずれにせよ、.NETからOracleにタイプを適切に変換する必要があります。このドキュメントにあることを正確にやっているように聞こえます:http://download.oracle.com/docs/html/e15167_01/featudts.htm#cjagfhba
edit2:自分で投稿した回答のコードに基づいて、それを修正するための(わずかに)より良い方法があるように見えます。
あなたはこのようないくつかの行をコメントしました:
//[07.12.2010]ISMAILH : ISNULLS ARE COMMENTED OUT FOR PROPER WORKING!
// TODO : Add code to initialise the object
//this.m_AMOUNTIsNull = true;
の目的 m_AMOUNTIsNull
(またはプロパティ AMOUNTIsNull
そのフィールドを使用する)は、コードが実際のものを区別できるようにすることです m_AMOUNT
デフォルトの.NET値(小数の場合は0)が使用されているため、設定された値と設定された値。
そのため、UDTが入力される前に値がチェックされます m_AMOUNT
価値:
if ((AMOUNTIsNull == false)) {
Oracle.DataAccess.Types.OracleUdt.SetValue(con, pUdt, "AMOUNT", this.AMOUNT);
UDTがデータベースからフェッチされたら、 AMOUNTIsNull
データベースフィールドが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")));
}
しかし、あなたがあなたの.NETオブジェクトを使用して、 AMOUNT
財産、 AMOUNTIsNull
変更されません:
[OracleObjectMappingAttribute("AMOUNT")]
public decimal AMOUNT {
get {
return this.m_AMOUNT;
}
set {
this.m_AMOUNT = value;
}
}
それを変更して適切に設定されている場合(そして、すでに作成したコメントアウトされた修正を元に戻す)、値を保存し、ヌル値を表すことができるので、あなたはより良い方が良いでしょう。
[OracleObjectMappingAttribute("AMOUNT")]
public decimal AMOUNT {
get {
return this.m_AMOUNT;
}
set {
this.AMOUNTIsNull = false;
this.m_AMOUNT = value;
}
}
他のヒント
Oracle ODP.NET Visual Studioプラグインによる自動生成クラスをチェックアウトした後、当社の.NET開発者は、自動生成コードのいくつかの行にコメントした後に正常に機能することを発見しました。
"// [07.12.2010] ISMAILH:ISNULLSは適切な作業のためにコメントアウトされています!」
その後、すべてが適切に機能しましたが、それのより深い理由について疑問に思います。そもそもプラグインがこれらの行を生成したのはなぜですか? :
//------------------------------------------------------------------------------
// <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()
{
}
}