Qualcuno sa come implementare Oracle Advance Queue da C# usando PL/SSQL e ODP.NET? Non riesco a trovare un singolo esempio o risorsa con esempi concreti in C# o VB.NET. Idealmente vorrei alcuni esempi su come accodare e decodificare i messaggi con tipi semplici (XMl/stringa).Oracle Advanced Queuing con .Net
risposta
Non posso aiutarti con le migliori pratiche, ma posso aiutarti con una coda UDT. Prima di gestire la coda, è necessario generare tipi personalizzati dal database nel progetto C#. Supponendo che Visual Studio e ODP.NET siano installati, è sufficiente connettersi al database tramite Server Explorer, individuare i tuoi UDT, fare clic con il tasto destro e scegliere "Genera classe personalizzata ..." Queste classi si mappano direttamente ai tuoi UDT e vengono utilizzate per memorizzare le informazioni dequeued.
Ecco un esempio del codice si usa per accodare un messaggio:
private void main(string[] args)
{
string _connstring = "Data Source=host/DB;User
Id=USER;Password=PASSWORD1;";
OracleConnection _connObj = new OracleConnection(_connstring);
// Create a new queue object
OracleAQQueue _queueObj = new OracleAQQueue("UDT_NAME", _connObj);
_connObj.Open();
OracleTransaction _txn = _connObj.BeginTransaction();
// Set the payload type to your UDT
_queueObj.MessageType = OracleAQMessageType.Udt;
_queueObj.UdtTypeName = "UDT_NAME";
// Create a new message object
OracleAQMessage _msg = new OracleAQMessage();
// Create an instance of JobClass and pass it in as the payload for the
// message
UDT_CUSTOM_CLASS _custClass = new UDT_CUSTOM_CLASS();
// Load up all of the properties of custClass
custClass.CustString = "Custom String";
custClass.CustInt = 5;
_msg.Payload = custClass;
// Enqueue the message
_queueObj.EnqueueOptions.Visibility = OracleAQVisibilityMode.OnCommit;
_queueObj.Enqueue(_msg);
_txn.Commit();
_queueObj.Dispose();
_connObj.Close();
_connObj.Dispose();
_connObj = null;
}
E 'un processo simile per annullare l'accodamento:
private void main(string[] args)
{
string _connstring = "Data Source=host/DB;User
Id=USER;Password=PASSWORD1;";
OracleConnection _connObj = new OracleConnection(_connstring);
// Create a new queue object
OracleAQQueue _queueObj = new OracleAQQueue("UDT_NAME", _connObj);
// Set the payload type to your UDT
_queueObj.MessageType = OracleAQMessageType.Udt;
_queueObj.UdtTypeName = "UDT_NAME";
_connObj.Open();
OracleTransaction _txn = _connObj.BeginTransaction();
// Dequeue the message.
_queueObj.DequeueOptions.Visibility = OracleAQVisibilityMode.OnCommit;
_queueObj.DequeueOptions.Wait = 10;
OracleAQMessage _deqMsg = _queueObj.Dequeue();
UDT_CUSTOM_CLASS data = (UDT_CUSTOM_CLASS)_deqMsg.Payload;
// At this point, you have the data and can do whatever you need to do with it
_txn.Commit();
_queueObj.Dispose();
_connObj.Close();
_connObj.Dispose();
_connObj = null;
}
Questo è un esempio di "semplice". Ne ho ricavato la maggior parte da Pro ODP.NET per Oracle Database 11g di Ed Zehoo. È un libro eccellente e lo raccomando vivamente di aiutarti a comprendere meglio i dettagli di OPD.NET. È possibile acquistare l'eBook qui: http://apress.com/book/view/9781430228202. Se inserisci il codice coupon MACWORLDOC, puoi ottenere l'eBook a $ 21,00. Questa offerta è valida solo per l'eBook che viene fornito in un formato PDF protetto da password. Spero che aiuti!
AQ ha un'interfaccia plsql tramite DBMS_AQ [adm]. Tutto ciò di cui hai bisogno è eseguire i pacchetti dal tuo ambiente e esempi e configurazioni AQ comuni. Non penso che ci sia qualcosa di speciale quando chiami quei pacchetti da C#.
Non conosco la risposta esatta a questo problema, ma qui è quello che abbiamo fatto:
- Prima ogni applicazione .NET che hanno bisogno di ascoltare sulla ESB (ESB è costruita su AQ) deve usare il proprio DB Oracle locale e rimuove i messaggi da lì. I messaggi vengono propagati alle code locali. Questo risolve il potenziale problema di scalabilità legato al mantenimento di una connessione DB aperta per ricevere i messaggi.
- In secondo luogo abbiamo creato la nostra libreria AQ che incapsula in modo semplice le stored procedure. - questo non è più necessario poiché Oracle ha finalmente rilasciato un ODAC 11.1.0.7.20 (con un ODP.NET che supporta AQ). Utilizziamo i tipi Oracle come DTO per definire i contratti dei messaggi.
La seconda opzione è ciò che ho fatto per desinteggiare. È interessante notare che hanno aggiunto il supporto adeguato in .NET tramite ODP.NET. – RichardOD
Ecco un bell'esempio che ho trovato da Oracle.
http://www.oracle.com/technetwork/issue-archive/2009/09-nov/o69net-099734.html
Codice: http://www.oracle.com/technetwork/issue-archive/2009/09-nov/o69odt-131369.zip
ho avuto un requisito in cui ho dovuto accodare/messaggi UDT dequeue a una coda. Questo post è stato davvero utile. Ha quasi tutto ma manca la creazione di un "Oracle Custom Type". Ho pensato che valesse la pena aggiungere quel codice qui in modo che la soluzione fosse completa.
Per Enqueue/rimozione in Oracle:
utente con il ruolo "AQ_ADMINISTRATOR_ROLE" deve essere creato. Nell'esempio seguente, "AQUSER" viene creato con quel ruolo.
PL Sql to EnQueue:
DECLARE
queue_options DBMS_AQ.ENQUEUE_OPTIONS_T;
message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
message_id RAW(16);
my_message AQUSER.USER_DEFINED_TYPE;
BEGIN
my_message := AQUSER.USER_DEFINED_TYPE('XXX','YYY','ZZZ');
DBMS_AQ.ENQUEUE(
queue_name => 'AQUSER.QUEUE_NAME',
enqueue_options => queue_options,
message_properties => message_properties,
payload => my_message,
msgid => message_id);
COMMIT;
END;
/
PL SQL to DeQueue
DECLARE
queue_options DBMS_AQ.DEQUEUE_OPTIONS_T;
message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
message_id RAW(2000);
my_message AQUSER.USER_DEFINED_TYPE;
BEGIN
DBMS_AQ.DEQUEUE(
queue_name => 'AQUSER.QUEUE_NAME',
dequeue_options => queue_options,
message_properties => message_properties,
payload => my_message,
msgid => message_id);
COMMIT;
END;
/
-------------------------------------------------------------------------------------------
To create a Oracle Custom Type, you can use the following code:
public class CustomMessageType : IOracleCustomType, INullable
{
[OracleObjectMappingAttribute("XXXXX")]
public string XXXXX { get; set; }
[OracleObjectMappingAttribute("YYYYY")]
public string YYYYY { get; set; }
[OracleObjectMappingAttribute("ZZZZZ")]
public string ZZZZZ { get; set; }
public void FromCustomObject(Oracle.DataAccess.Client.OracleConnection con, IntPtr pUdt)
{
if (!string.IsNullOrEmpty(XXXXX))
{
OracleUdt.SetValue(con, pUdt, "XXXXX", XXXXX);
}
if (!string.IsNullOrEmpty(YYYYY))
{
OracleUdt.SetValue(con, pUdt, "YYYYY", YYYYY);
}
if (!string.IsNullOrEmpty(ZZZZZ))
{
OracleUdt.SetValue(con, pUdt, "ZZZZZ", ZZZZZ);
}
}
public void ToCustomObject(Oracle.DataAccess.Client.OracleConnection con, IntPtr pUdt)
{
XXXXX = (string)OracleUdt.GetValue(con, pUdt, "XXXXX");
YYYYY = (string)OracleUdt.GetValue(con, pUdt, "YYYYY");
ZZZZZ = (string)OracleUdt.GetValue(con, pUdt, "ZZZZZ");
}
public bool IsNull { get; set; }
}
[OracleCustomTypeMappingAttribute("SCHEMA.CUSTOM_TYPE")]
public class QueueMessageTypeFactory : IOracleCustomTypeFactory
{
public IOracleCustomType CreateObject()
{
return new CustomMessageType();
}
}
Spiacente ma che devo usare PL/SQL e stored procedure è già parte della domanda. Il problema è che quando si eliminano i messaggi sono disponibili molte opzioni, ad es. il timeout della connessione. Anche gli UDT sono usati come parametri per il processo di archiviazione dei depositi - non so come creare UDT da .Net con 10G. Quello che sto cercando sono alcuni esempi di codice C# e best practice (ad esempio chiudere la connessione db o lasciarlo aperto ???) – Geo
Qualcuno ha qualche esempio su questo? Sto anche cercando questo. ;) – user171523