No soy el primero en tener estos problemas, y voy a enumerar algunas publicaciones de referencia a continuación, pero sigo buscando una solución adecuada.Problemas al llamar al procedimiento almacenado desde C# con CLOB grande
Necesito llamar a un procedimiento almacenado (base de datos Oracle 10g) desde un servicio web C#. El servidor web tiene un cliente Oracle 9i instalado y estoy usando Microsofts System.Data.OracleClient
.
El procedimiento toma un XML como un CLOB. Cuando el XML era más de 4000 Bytes (que es probable que en un caso de uso normal), tropecé con el siguiente error:
ORA-01460 - unimplemented or unreasonable conversion requested
que he encontrado this, this y this puesto.
Además, encontré una solución prometedora que no llama al procedimiento almacenado directamente desde C#, sino que define un fragmento de código PL/SQL anónimo. Este código se ejecuta como un OracleCommand. El XML está incrustado como una cadena literal y el llamado procedimiento se realiza desde dentro de ese trozo de código:
private const string LoadXml =
"DECLARE " +
" MyXML CLOB; " +
" iStatus INTEGER; " +
" sErrMessage VARCHAR2(2000); " +
"BEGIN " +
" MyXML := '{0}'; " +
" iStatus := LoadXML(MyXML, sErrMessage); " +
" DBMS_OUTPUT.ENABLE(buffer_size => NULL); " +
" DBMS_OUTPUT.PUT_LINE(iStatus || ',' || sErrMessage); " +
"END;";
OracleCommand oraCommand = new OracleCommand(
string.Format(LoadXml, xml), oraConnection);
oraCommand.ExecuteNonQuery();
Desafortunadamente, este enfoque ahora falla tan pronto como el XML es más de 32 KBytes más o menos, que todavía es muy probable en mi aplicación. Esta vez se deriva el error del compilador de PL/SQL que dice:
ORA-06550: line1, column 87: PLS-00172: string literal too long
Después de algunas investigaciones que concluyen que no es simplemente viable para resolver el problema con mi segundo enfoque.
Siguiendo las publicaciones mencionadas, tengo las siguientes dos opciones.
- Switch to ODP.NET (ya que se supone que es un error en el cliente de base de datos obsoleta de Microsoft)
- Insert the CLOB into a table y hacer que la lectura procedimiento almacenado desde allí
(The first post dijo que algunos clientes son errores, pero el mío (9i) no entra en el rango mencionado de las versiones 10g/11g.)
Puede confirmar que estos son los solo quedan dos opciones? ¿O hay otra forma de ayudarme?
Solo para aclarar: el XML no se finalmente se guardarán en cualquier mesa, pero es procesado por el procedimiento almacenado que inserta algunos registros de alguna tabla basada en el contenido XML.
Mis consideraciones acerca de las dos opciones:
- El cambio a ODP.NET es difícil porque tengo que instalarlo en un servidor web en la que no tengo acceso al sistema hasta ahora, y porque podríamos También quiero implementar la pieza de código en los clientes, por lo que cada cliente debería instalar ODP.NET como parte de la implementación.
- El desvío sobre una tabla hace que el código del cliente sea un poco más complicado y también requiere bastante esfuerzo en la base de datos para adaptar/extender las rutinas PL/SQL.
BLOB or CLOB, typo. – Benny
@Benny: El problema existe para ans LOB, de ahí las publicaciones BLOB a las que se hace referencia, pero tuve problemas con CLOB. No puedo encontrar ningún error tipográfico en mi publicación ... – chiccodoro
'MyXML: = '{0}';' the 'string.Format()' está reemplazando ''{0}'' con el xml - sin embargo, '' ... '' es un literal de cadena que es del tipo de datos 'VARCHAR2' (no un' CLOB'). [PL/SQL tiene un límite de 32k] (http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/datatypes.htm#i43252) en 'VARCHAR2's y por eso falla. – MT0