2009-08-12 15 views
7

¿Alguien sabe cómo implementar Oracle Advance Queue desde C# usando PL/SSQL y ODP.NET? No puedo encontrar un solo ejemplo o recurso con ejemplos concretos en C# o VB.NET. Lo ideal sería que quisiera algunos ejemplos sobre cómo enqueue y dequeue mensajes con tipos simples (XMl/string).Oracle Advanced Queuing con .Net

Respuesta

14

No puedo ayudarte con las mejores prácticas, pero puedo ayudarte con una cola UDT. Antes de ocuparse de la cola, debe generar tipos personalizados desde la base de datos en su proyecto C#. Suponiendo que tiene instalado Visual Studio y ODP.NET, simplemente necesita conectarse a la base de datos a través del Explorador del servidor, ubicar sus UDT, hacer clic con el botón secundario y elegir "Generar clase personalizada ..." Estas clases se asignan directamente a sus UDT y se usan para almacenar la información Dequeued.

Aquí se muestra un ejemplo del código que se utiliza para poner en cola un mensaje:

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 un proceso similar al quitar de la cola:

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; 

} 

Eso es un ejemplo de "simple". Saqué la mayor parte de Pro ODP.NET para Oracle Database 11g de Ed Zehoo. Es un libro excelente y lo recomiendo encarecidamente para ayudarlo a comprender mejor los pormenores de todo lo que hace OPD.NET. Puede comprar el eBook aquí: http://apress.com/book/view/9781430228202. Si ingresa el código de cupón MACWORLDOC, puede obtener el eBook por $ 21.00. Esa oferta solo es válida para el libro electrónico que viene en formato PDF protegido con contraseña. ¡Espero que esto ayude!

0

AQ tiene una interfaz plsql vía DBMS_AQ [adm]. Todo lo que necesita es ejecutar esos paquetes desde su entorno y los ejemplos y configuraciones comunes de AQ. No creo que haya nada especial cuando llames a esos paquetes desde C#.

+0

Lo sentimos, pero que tengo que usar PL/SQL y procedimientos almacenados es allready parte de la pregunta. El problema es que, al eliminar mensajes, hay muchas opciones disponibles, p. el tiempo de espera de la conexión. También se usa UDT como parámetro para el proceso de almacenamiento de dequeue - No sé cómo crear UDT desde .Net con 10G. Lo que estoy buscando son algunos ejemplos del código C# y las mejores prácticas (por ejemplo, cerrar la conexión db o dejarla abierta ???) – Geo

+0

¿Alguien tiene algún ejemplo al respecto? También estoy buscando esto. ;) – user171523

3

No sé la respuesta exacta a este problema, pero aquí es lo que hicimos:

  • En primer lugar todas las aplicaciones .NET que necesita para escuchar en la ESB (ESB es construir sobre AQ) tiene que usar su propio Oracle DB local y dequeue mensajes desde allí. Los mensajes se propagan a las colas locales. Esto resuelve el problema de escalabilidad potencial vinculado a mantener abierta una conexión de BD para recibir mensajes.
  • En segundo lugar, construimos nuestra propia biblioteca AQ que encapsula básicamente los procedimientos almacenados. - Esto ya no es necesario ya que Oracle finalmente lanzó un ODAC 11.1.0.7.20 (con un ODP.NET que admite AQ). Usamos tipos de Oracle como una especie de DTO para definir los contratos de mensajes.
+0

La segunda opción es lo que hice para quitar la cola. Es interesante ver que han agregado soporte adecuado en .NET a través de ODP.NET. – RichardOD

1

que tenía un requisito donde tenía que poner en cola/UDT dequeue a una cola. Esta publicación fue realmente útil. Tiene casi todo pero falta la creación de un "Tipo personalizado de Oracle". Pensé que vale la pena agregar ese código aquí para que la solución esté completa.

Para poner en cola/retirada de cola en Oracle:

usuario con el rol "AQ_ADMINISTRATOR_ROLE" tiene que ser creado. En el ejemplo siguiente, se crea el "AQUSER" con esa función.

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