c# - How to get ODP.NET to return null value for User Defined Type from out parameter in Oracle stored procedure? -
i having trouble odp.net regards udt (user defined type) behavior.
my problem arises when have a procedure containing out parameter returns specific udt.
when return an instantiated udt out parameter there no problem.
when return a null value out parameter i nullreference error:
a first chance exception of type 'system.nullreferenceexception' occurred in oracle.dataaccess.dll
i have tried setting isnullable = true on relevant oraclecommand parameter without success.
i have no problem sending , receiving rather complex udt's, e.g. udt's nested udt's , collections of objects , udt's witgh nested collections of objects.
any ideas if can solved using odp.net other making oracle procedure return instance of object type?
update - solved:
the issue udt type nested udt type not correctly initialized null. using auto generated code solved problem.using oracle user-defined types .net , visual studio
christian shay, thank resolving issue - auto generated code perhaps better choice implementing base classes handle of behavior, although possible.
the oracle stored procedure signature is:
procedure create_definitions_for_group( p_grp_no in number ,p_date in date ,p_error_code out myschema.error_code);
i call code in c# using odp.net after opening connection:
using (var ocmd = new oraclecommand { commandtext = "myschema.mypackage.create_definitions_for_group", connection = oconn, commandtype = commandtype.storedprocedure }) { try { ocmd.parameters.add(oracleparameterfactory.createinparam( "p_grp_no", oracledbtype.int64, value: groupno)); ocmd.parameters.add(oracleparameterfactory.createinparam( "p_date", oracledbtype.date, value: dateofgroup)); ocmd.parameters.add(oracleparameterfactory.createoutparamforudttype( "p_error_code", "myschema.error_code")); ocmd.executenonquery(); var report = ocmd.parameters["p_error_code"].value dberrorcode; return report; } { commandhelpers.disposeparameters(ocmd); } }
the udt type defined valid udt type in .net this:
public class dberrorcode : typetemplate { [oracleobjectmapping("error_code")] public decimal code { get; set; } [oracleobjectmapping("description")] public string description { get; set; } }
the base typetemplate class defined this:
public class typetemplate : ioraclecustomtype, inullable { public virtual void fromcustomobject(oracleconnection con, intptr pudt) { foreach (var p in gettype().getproperties()) { // must ignore these 2 properties if (p.name == "null" || p.name == "isnull") continue; var oracleobjectmappingattribute = p.getcustomattributes(typeof(oracleobjectmappingattribute), false)[0] oracleobjectmappingattribute; if (oracleobjectmappingattribute == null) continue; var attributename = oracleobjectmappingattribute.attributename; if (p.getcustomattributes(typeof(ignoreattribute), false).length == 0) { if (p.getcustomattributes(typeof(nullableattribute), false).length == 0) { oracleudt.setvalue(con, pudt, attributename, p.getvalue(this, null)); } else { if (p.getvalue(this, null) != null) { oracleudt.setvalue(con, pudt, attributename, p.getvalue(this, null)); } } } } } public virtual void tocustomobject(oracleconnection con, intptr pudt) { foreach (var p in gettype().getproperties()) { // must ignore these 2 properties if (p.name == "null" || p.name == "isnull") continue; var oracleobjectmappingattribute = p.getcustomattributes(typeof(oracleobjectmappingattribute), false)[0] oracleobjectmappingattribute; if (oracleobjectmappingattribute == null) continue; var attributename = oracleobjectmappingattribute.attributename; if (!oracleudt.isdbnull(con, pudt, attributename)) { p.setvalue(this, oracleudt.getvalue(con, pudt, attributename), null); } } } #region inullable members public bool isnull { get; private set; } public static typetemplate null { { var obj = new typetemplate { isnull = true }; return obj; } } #endregion }
the method in oracleparameterfactory udt parameter follows (exception handling removed code present clean code possible - error produced not come exception handling):
public static oracleparameter createoutparamforudttype( string paramname, string udtname, object value, bool isnullable = false) { var param = new oracleparameter { parametername = paramname, udttypename = udtname.toupperinvariant(), oracledbtype = oracledbtype.object, direction = parameterdirection.output, isnullable = isnullable }; if (value != null) { param.value = value; } return param; }
problem solved: issue udt type nested udt type not correctly initialized null. using auto generated code solved problem.using oracle user-defined types .net , visual studio
christian shay, thank resolving issue - auto generated code perhaps better choice implementing base classes handle of behavior, although possible.
Comments
Post a Comment