2009-08-12 9 views
7

Jemand weiß, wie Oracle Advance Queue aus C# mit PL/SSQL und ODP.NET zu implementieren? Ich kann kein einzelnes Beispiel oder Ressource mit konkreten Beispielen in C# oder VB.NET finden. Idealerweise hätte ich gern einige Beispiele, wie Nachrichten mit einfachen Typen (XMl/string) in Warteschlangen eingereiht und herausgenommen werden.Oracle Advanced Queuing mit .Net

Antwort

14

Ich kann Ihnen nicht mit den Best Practices helfen, aber ich kann Ihnen mit einer UDT-Warteschlange helfen. Bevor Sie mit der Warteschlange arbeiten, müssen Sie benutzerdefinierte Typen aus der Datenbank in Ihrem C# -Projekt generieren. Angenommen, Sie haben Visual Studio und ODP.NET installiert, müssen Sie lediglich über den Server-Explorer eine Verbindung mit der Datenbank herstellen, Ihre UDTs suchen, mit der rechten Maustaste klicken und "Benutzerdefinierte Klasse generieren" auswählen. Diese Klassen werden direkt Ihren UDTs zugeordnet und verwendet um die ausgedruckten Informationen zu speichern. Hier

ist ein Beispiel für den Code würde verwenden Sie eine Nachricht an einreihen:

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; 
} 

Es ist ein ähnlicher Prozess aus der Warteschlange entfernt:

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; 

} 

, dass ein „einfaches“ Beispiel ist. Ich habe das meiste aus Pro ODP.NET für Oracle Database 11g von Ed Zehoo rausgeholt. Es ist ein ausgezeichnetes Buch und ich empfehle es dringend, um Ihnen zu helfen, ein besseres Verständnis für alle Aspekte von OPD.NET zu bekommen. Sie können das eBook hier kaufen: http://apress.com/book/view/9781430228202. Wenn Sie den Gutscheincode MACWORLDOC eingeben, können Sie das eBook für 21,00 $ erhalten. Dieses Angebot ist nur gut für das eBook, das in einem passwortgeschützten PDF-Format kommt. Ich hoffe das hilft!

0

AQ hat plsql Schnittstelle über DBMS_AQ [adm]. Alles, was Sie brauchen, ist, dass Sie diese Pakete von Ihrer Umgebung und allgemeinen AQ-Beispielen und Setup ausführen. Ich denke nicht, dass es etwas besonderes gibt, wenn man diese Pakete von C# anruft.

+0

Entschuldigung, aber dass ich PL/SQL und gespeicherte Prozeduren verwenden muss, ist schon ein Teil der Frage. Das Problem besteht darin, dass beim Löschen von Nachrichten viele Optionen verfügbar sind, z. das Timeout der Verbindung. Auch UDT werden als Parameter für den Dequeue-Speicherproc verwendet - ich weiß nicht, wie man UDT aus .Net mit 10G erstellt. Was ich suche, sind einige Beispiele für C# -Code und Best Practices (z. B. schließen Sie die DB-Verbindung oder lassen Sie sie offen ???) – Geo

+0

Hat jemand ein Beispiel dafür? Ich suche auch danach. ;) – user171523

3

Ich weiß nicht, die genaue Antwort auf dieses Problem, aber hier ist das, was wir haben:

  • Erste jeder .net-Anwendung, die auf dem ESB hören müssen (ESB auf AQ bauen) hat zu verwenden, seine eigene lokale Oracle DB und entnimmt Nachrichten von dort. Die Nachrichten werden an die lokalen Warteschlangen weitergegeben. Dies löst das potenzielle Skalierbarkeitsproblem, das damit verbunden ist, eine DB-Verbindung offen zu halten, um Nachrichten zu empfangen.
  • Zweitens bauten wir unsere eigene AQ-Bibliothek, die gespeicherte Prozeduren grundlegend verkapselt. - Dies wird nicht mehr benötigt, da Oracle das ODAC 11.1.0.7.20 (mit einem ODP.NET, das AQ unterstützt) finally veröffentlicht hat. Wir verwenden Oracle-Typen als eine Art DTO, um die Nachrichtenverträge zu definieren.
+0

Die zweite Option ist, was ich aus der Warteschlange genommen habe. Interessant zu sehen, dass sie in .NET über ODP.NET richtig unterstützt haben. – RichardOD

1

hatte ich eine Anforderung, wo ich in eine Warteschlange/dequeue UDT Nachrichten einreihen musste. Dieser Beitrag war wirklich hilfreich. Es hat fast alles außer der Erstellung eines "Oracle Custom Type" fehlt. Ich dachte, es lohnt sich, diesen Code hier hinzuzufügen, damit die Lösung vollständig ist.

einzureihen/DEQUEUE in Oracle:

Benutzer mit Rolle "AQ_ADMINISTRATOR_ROLE" erstellt werden muss. Im folgenden Beispiel wird der "AQUSER" mit dieser Rolle erstellt.

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(); 
     } 
    }