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和 odp.net 插入。我们正处于插入NVARCHAR2数据类型中的.NET应用程序发送的值。数字或日期数据类型的数据不能插入。有任何想法吗?
解决方案
您的问题可能是由于您的调用C#代码到Oracle类型(数字,日期)中的键入c#代码中的类型转换,用于将值存储在数据库中。确保UDT类使用Oracle类型,而不是.NET类型。
另外,如果您要做的就是迭代您的集合以插入记录,则应考虑使用Oracle的散装绑定功能,因为它将更加有效。看 http://dotnetslackers.com/articles/ado_net/bulkoperationsusingoracledataproviderfornetodpnet.aspx 一个很好的例子。
编辑:按照您的敬意:“我们正在寻找一个直接的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填充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开发人员发现它在评论自动生成的代码中的某些行后正常工作,在行之后开始4行
“ // [07.12.2010] Imprh: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()
{
}
}