带有.Net的Oracle Advanced Queuing

时间:2009-08-12 12:02:32

标签: .net oracle

有人知道如何使用PL / SSQL和ODP.NET从C#实现Oracle Advance Queue? 我在C#或VB.NET中找不到具有具体示例的单个示例或资源。 理想情况下,我想了解一些关于如何使用简单类型(XMl / string)对消息进行入队和出列的示例。

5 个答案:

答案 0 :(得分:17)

我无法帮助您掌握最佳实践,但我可以帮助您使用UDT队列。在处理队列之前,需要从数据库生成自定义类型到C#项目中。假设您安装了Visual Studio和ODP.NET,您只需要通过Server Explorer连接到数据库,找到您的UDT,右键单击并选择“Generate Custom Class ...”这些类直接映射到您的UDT并使用存储出列信息。

以下是用于排队邮件的代码示例:

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

这是一个类似的出队过程:

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;

}

这是一个“简单”的例子。我从Ed Zehoo的Pro ODP.NET for Oracle Database 11g中删除了大部分内容。这是一本很好的书,我强烈建议它帮助你更好地理解OPD.NET所有东西的来龙去脉。您可以在此处购买电子书:http://apress.com/book/view/9781430228202。如果您输入优惠券代码MACWORLDOC,您可以以21.00美元的价格购买电子书。该优惠仅适用于受密码保护的PDF格式的电子书。我希望这有帮助!

答案 1 :(得分:3)

我不知道这个问题的确切答案,但这就是我们所做的:

  • 首先,每个需要在ESB上监听的.net应用程序(ESB都是基于AQ构建)必须使用自己的本地Oracle数据库并从那里出列消息。消息将传播到本地队列。这解决了与保持数据库连接打开以接收消息相关的潜在可伸缩性问题。
  • 其次,我们构建了自己的AQ库,它基本上封装了存储过程。 - 由于Oracle最终发布了ODAC 11.1.0.7.20(支持AQ的ODP.NET),因此不再需要这样做了。我们使用Oracle类型作为DTO来定义消息契约。

答案 2 :(得分:3)

我有一个要求,我必须将UDT消息排队/出列到队列。这篇文章真有帮助。几乎所有东西都缺少了“Oracle Custom Type”的创建。我认为值得在这里添加代码,以便解决方案完整。

到Oracle的EnQueue / DeQueue:

必须创建角色为“AQ_ADMINISTRATOR_ROLE”的用户。在下面的示例中,使用该角色创建“AQUSER”。

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

答案 3 :(得分:2)

答案 4 :(得分:0)

AQ通过DBMS_AQ [adm]有plsql接口。您只需要从您的环境和常见的AQ示例和设置中运行这些包。当您从c#调用这些包时,我认为没有什么特别的。