Come posso aggiornare i dati nei campi CLOB usando una >> query preparata << con ODP (Oracle.DataAccess)?

Sto cercando di eseguire una query sql preparata che aggiorna i campi CLOB in un database Oracle 10g (10.2.0.1).

Se eseguo la seguente query da SQL Developer e fornisco i valori per i segnaposto, non esiste alcun prblem. Se tuttavia lo eseguo tramite OracleCommand (Oracle.DataAccess.dll, versione 1.102.0.1 (penso), .NET Framework 3.5), viene visualizzato il seguente messaggio di errore. Si noti che non stiamo utilizzando il client Oracle predefinito in quanto richiediamo l’inserimento di massa. La data versione di ODP e la versione di .NET Framework sono purtroppo un requisito difficile e non possiamo cambiarlo.

Query:

 UPDATE master_table SET description = :description, modification_notes = :modification_notes WHERE master_id = :master_id; 

Errore:

ORA-00932: tipi di dati incoerenti: previsto – ottenuto CLOB

Ulteriore inormazione:

I parametri sono assegnati come segue:

 var param_description = new OracleParameter(":description", OracleDbType.Clob); param_description.Value = "Test"; 

Ho provato le seguenti cose:

  • inserisci to_clob() nella query SQL
  • assegnare un object Oracle.DataAccess.Types.OracleClob al parametro.

Ho anche trovato la seguente descrizione, ma vorrei davvero essere in grado di mantenere la query preparata.

Come inserire il campo CLOB in Oracle usando C #

È ansible farlo attraverso una query preparata?

Ho allegato un esempio completo che produce l’errore. DESCRIPTION e MODIFICATION_NOTES sono due colonne di tipo CLOB nel database.


Dati in ingresso:

  • connessione: OracleConnection al database
  • master_id: chiave primaria da filtrare

Codice:
Dichiarazione di non responsabilità: ho digitato il seguente esempio a mano, potrebbero esserci degli errori che non si trovano nel codice reale

 var query = "UPDATE master_table " + "SET description = :description " + " modification_notes = :modification_notes " + "WHERE master_id = :master_id"; var param_master_id = new OracleParameter(":master_id", OracleDbType.Int64); param_master_id.Value = master_id; var param_description = new OracleParameter(":description", OracleDbType.Clob); param_description.Value = "Test1"; var param_master_id = new OracleParameter(":modification_notes", OracleDbType.Clob); param_description.Value = "Test2"; IDbCommand command = new OracleCommand(query, connection); command.parameters.Add(param_master_id); command.parameters.Add(param_description); command.parameters.Add(param_modification_notes); command.ExecuteNonQuery(); // this line throws an exception 

È necessario impostare su true se si desidera associare per nome. L’impostazione predefinita è vincasting dall’ordine del parametro aggiunto.

 cmd.BindByName = true; 

Modifica: la mia risposta di seguito si applica all’utilizzo tipico di Clob in cui la dimensione è maggiore di 32k (per cosa sono stati progettati). Se sai che vincerai sempre meno di 32k byte, o 16k caratteri nel solito caso di unicode puoi vincolarti come Varchar2 e liberarti dal dover creare un lob temporaneo.

Tieni presente che un LOB in una colonna Oracle è in realtà un Locator LOB, un puntatore ai dati effettivi. Prima di poter aggiornare una colonna CLOB con Lob Locator, è necessario prima creare e compilare un CLOB temporaneo.

Nella directory degli esempi di ODP.NET nella tua Oracle Home dovrebbe esserci una directory LOB, in quanto sembra che samples5.cs possa essere un buon punto di partenza. Ecco un frammento da esso:

  // Set the command OracleCommand cmd = new OracleCommand( "update multimedia_tab set story = :1 where thekey = 1"); cmd.Connection = con; cmd.CommandType = CommandType.Text; // Create an OracleClob object, specifying no caching and not a NCLOB OracleClob clob = new OracleClob(con, false, false); // Write data to the OracleClob object, clob, which is a temporary LOB string str = "this is a new story"; clob.Write(str.ToCharArray(), 0, str.Length); // Bind a parameter with OracleDbType.Clob cmd.Parameters.Add("clobdata", OracleDbType.Clob, clob, ParameterDirection.Input); try { // Execute command cmd.ExecuteNonQuery(); 

Vedi la risposta accettata per la soluzione reale.

[Modifica: precedente risposta sospetta]:
Dopo diversi giorni di test e debug ho trovato la soluzione che era così lontana da tutto quello che ho considerato:

Apparentemente, è necessario associare tutti i campi di Clob prima di bind qualcos’altro, anche quando si usano segnaposti effettivi invece di usare :1 Clob :2 ecc.

La modifica dell’ordine di binding (ovvero l’ordine delle chiamate AddParameter ) l’ha AddParameter .

Prova questo :

  string Query3 = " DECLARE " + "str varchar2(32767); " + " BEGIN " + " str := '" + base64ImageRepresentationLogo + "'; " + " update map_general_settings set value=str where DESC_AR='LOGO_IMG' ; END; "; command.CommandText = Query3; command.ExecuteNonQuery();