2009-08-12 29 views
7

Ai đó biết cách triển khai Hàng đợi Trước của Oracle từ C# bằng cách sử dụng PL/SSQL và ODP.NET? Tôi không thể tìm thấy một ví dụ hoặc tài nguyên đơn lẻ với các ví dụ cụ thể trong C# hoặc VB.NET. Lý tưởng nhất là tôi muốn một số ví dụ về cách thông điệp enqueue và dequeue với các loại đơn giản (XMl/string).Xếp hạng Nâng cao của Oracle với .Net

Trả lời

14

Tôi không thể giúp bạn với các phương pháp hay nhất, nhưng tôi có thể giúp bạn với Hàng đợi UDT. Trước khi bạn xử lý hàng đợi, bạn cần tạo các kiểu tùy chỉnh từ cơ sở dữ liệu vào dự án C# của bạn. Giả sử bạn đã cài đặt Visual Studio và ODP.NET, bạn chỉ cần kết nối với cơ sở dữ liệu thông qua Server Explorer, định vị UDT của bạn, nhấp chuột phải và chọn "Tạo lớp tùy chỉnh ..." Các lớp này ánh xạ trực tiếp tới UDT của bạn và được sử dụng để lưu trữ thông tin Dequeued.

Dưới đây là một ví dụ về mã bạn sẽ sử dụng để enqueue nhắn:

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

Đó là một quá trình tương tự để dequeue:

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; 

} 

Đó là một "đơn giản" chẳng hạn. Tôi đã lấy phần lớn số đó ra khỏi Pro ODP.NET cho Oracle Database 11g bởi Ed Zehoo. Đó là một cuốn sách tuyệt vời và tôi khuyên bạn nên đọc nó để giúp bạn hiểu rõ hơn về những thứ trong và ngoài mọi thứ OPD.NET. Bạn có thể mua sách điện tử tại đây: http://apress.com/book/view/9781430228202. Nếu bạn nhập mã phiếu giảm giá MACWORLDOC, bạn có thể nhận sách điện tử với giá $ 21,00. Ưu đãi đó chỉ tốt cho sách điện tử có định dạng PDF được bảo vệ bằng mật khẩu. Tôi hi vọng cái này giúp được!

0

AQ có giao diện plsql qua DBMS_AQ [adm]. Tất cả những gì bạn cần là chạy các gói đó từ môi trường của bạn và các ví dụ và thiết lập AQ chung. Tôi không nghĩ rằng có bất cứ điều gì đặc biệt khi bạn gọi những gói đó từ C#.

+0

Xin lỗi, nhưng tôi phải sử dụng PL/SQL và các thủ tục lưu sẵn là một phần của câu hỏi. Vấn đề là khi khử thư, nhiều tùy chọn có sẵn, ví dụ: hết thời gian kết nối. Ngoài ra UDT được sử dụng làm tham số cho cửa hàng dequeue proc - Tôi không biết cách tạo UDT từ .Net với 10G. Những gì tôi đang tìm kiếm là một số ví dụ về mã C# và các phương pháp hay nhất (ví dụ: đóng kết nối db hoặc để nó mở?) – Geo

+0

Có bất kỳ ví dụ nào về điều này không? Tôi cũng đang tìm kiếm điều này. ;) – user171523

3

Tôi không biết câu trả lời chính xác cho vấn đề này nhưng đây là những gì chúng tôi đã làm:

  • Đầu tiên mọi ứng dụng .net rằng cần phải lắng nghe trên ESB (ESB được xây dựng trên AQ) có sử dụng Oracle DB của riêng mình và các thông điệp dequeue từ đó. Các thông báo được truyền đến hàng đợi cục bộ. Điều này giải quyết vấn đề khả năng mở rộng tiềm năng liên quan đến việc giữ kết nối DB mở để nhận tin nhắn.
  • Thứ hai, chúng tôi đã xây dựng thư viện AQ riêng của mình để đóng gói cơ bản các thủ tục được lưu trữ. - điều này không cần thiết nữa vì Oracle đã phát hành một ODAC 11.1.0.7.20 (với ODP.NET hỗ trợ AQ). Chúng tôi sử dụng các loại Oracle như là loại DTO để xác định các hợp đồng thông báo.
+0

Tùy chọn thứ 2 là những gì tôi đã làm để dequeue. Thật thú vị khi thấy họ đã thêm hỗ trợ thích hợp vào .NET thông qua ODP.NET. – RichardOD

1

Tôi đã có một yêu cầu mà tôi đã phải enqueue/tin nhắn UDT dequeue tới một hàng đợi. Bài đăng này thực sự hữu ích. Nó có hầu như tất cả mọi thứ nhưng việc tạo ra một "Oracle Custom Type" bị thiếu. Tôi nghĩ giá trị của nó thêm mã ở đây để giải pháp hoàn tất.

Để EnQueue/Dequeue trong Oracle:

người dùng với vai trò "AQ_ADMINISTRATOR_ROLE" phải được tạo ra. Trong ví dụ bên dưới, "AQUSER" được tạo với vai trò đó.

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(); 
     } 
    } 
Các vấn đề liên quan