【问题标题】:ODP.NET notifications are not received in the client side客户端未收到 ODP.NET 通知
【发布时间】:2020-03-31 00:12:07
【问题描述】:

我有以下部署:

A) 服务器机器:

  • Windows 7 - 64 位 - SP1(英文)
  • Oracle 数据库 11g 快捷版
  • ODAC 11.2.0.1.2(仅安装了 Oracle Instant Client 11.2.0.1.0)

B) 客户端机器:

  • Windows 7 - 32 位 - SP1(西班牙语)
  • 微软 .NET Framework 4.0
  • ODAC 11.2.0.1.2(完整安装)

在客户端机器中,我有一个非常简单的应用程序,它执行以下步骤:

  1. 创建一个 OracleConnection
  2. 创建 OracleCommand(从表中选择字段)
  3. 根据前面的命令创建一个 OracleDependency

执行完这些步骤后,我可以在 DBA_CHANGE_NOTIFICATION_REGS 表中看到已插入新记录。此记录中的信息与我的客户端设置(用户连接、IP 地址、IP 端口)完全匹配。

然后,我修改数据库以确保要通知的查询结果在此修改后发生更改。我的申请应该得到通知,但事实并非如此。

我已经检查(使用 Wireshark),修改后,一些流量通过 DBA_CHANGE_NOTIFICATION_REGS 中指定的端口从服务器发送到客户端,但客户端应用程序没有收到通知。

所以,似乎通知创建正确,从服务器到客户端计算机的通知也被发送,但通知没有到达应用程序。

为了接收通知,我还需要在客户端做什么?

提前谢谢....

这里是我使用的代码:

private void buttonConnectOracle_Click(object sender, EventArgs e)
{
    String constr = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.164.10.202)(PORT=30005))" + 
                    "(CONNECT_DATA=(SID=MASI)));User Id=dbuser;Password=dbuserpasswd;";

    try
    {
        OracleCon = new OracleConnection(constr);
        OracleCon.Open();
        buttonConectarOracle.Enabled = false;
        RegisterOracleCommandDependency();
    }
    catch (Exception E)
    {
        MessageBox.Show(String.Format("ERROR connecting with Oracle BD: {0}{0}Connection string: {1}{0}{0}Error:{0}{2}", "\n\r", constr, E.Message));
    }
}

private void RegisterOracleCommandDependency()
{
    String sql = "SELECT * FROM SCEHMA.REF";
    OracleCommand command = new OracleCommand(sql, OracleCon);

    OracleDep = new OracleDependency(command);
    command.Notification.IsNotifiedOnce = false;

    command.ExecuteNonQuery();

    OracleDep.OnChange += new Oracle.DataAccess.Client.OnChangeEventHandler(OnMyNotificationOracle);
}

public void OnMyNotificationOracle(object src, OracleNotificationEventArgs args) 
{
    String logStr = "Notification received at " + DateTime.Now.ToString();
    //TODO: Add logStr to log
}

【问题讨论】:

  • 您的客户端应用程序是 Web、控制台还是 Windows 应用程序?
  • 这是一个 Windows 应用程序。
  • 您查看过文档吗?我认为它包含您在“加载和运行更改通知演示应用程序”[3,4] 中寻找的内容。如果你让它工作,请告诉我。
  • 11.2 数据库和客户端中存在可能导致无法接收通知的问题。请在此处查看我的答案以确保您没有遇到该错误:stackoverflow.com/questions/25629461/…
  • 请发布您的代码

标签: oracle notifications odp.net


【解决方案1】:

首先,感谢@b_levitt、@yopez83 和@Christian Shay 的贡献。

问题已解决:部分Oracle Server版本与对应的Oracle Client版本存在不兼容问题。

总而言之,当服务器为 11.2.0.2.0 且客户端为 11.2.0.1.2 时,通知不起作用。

此查询提供有关 Oracle 服务器版本的信息:

select * from v$version;

在我的例子中,输出如下:

Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for 64-bit Windows: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

希望对您有所帮助....

【讨论】:

【解决方案2】:

只是添加到上面列出的不兼容版本中; 我在使用 Oracle 11g 版本 11.2.0.3.0(64 位)和使用 ODP.NET (Oracle.ManagedDataAccess) 版本 12.1.24160719 时遇到了同样的问题。

在 USER_CHANGE_NOTIFICATION_REGS 表中获取一个条目(但是,主机 IP 与我的客户端 IP 不匹配,嗯...)此条目在大约 30 秒后被删除。 OnChangeEventHandler 在插入时从未在 .Net 客户端中触发(使用基于对象的通知)。

两者都有:

GRANT CHANGE NOTIFICATION TO [USER]
GRANT EXECUTE ON DBMS_CHANGE_NOTIFICATION TO [USER]

现在尝试了 nuget 提供的其他 ODP.NET 客户端版本,低至 10.1.21。没有工作。在执行插入时,Wireshark 在端口 1005(由 OracleDependency 使用)上没有检测到任何流量。叹息。

更新:事实证明,回调失败是由于在服务器上设置了 IP 重定向,所以在这种情况下不怪 Oracle... 提示始终是验证 IP 地址在 USER_CHANGE_NOTIFICATION_REGS 中指定。

【讨论】:

    【解决方案3】:

    检查此documentation。我认为它会帮助您处理通知。

    另外,如果上一个链接没有帮助,请参阅 this。

    【讨论】:

      【解决方案4】:

      也许这会有所帮助

      using (OracleConnection OraConn = new OracleConnection(conString))
      {
          using (OracleCommand OraComm = OraConn.CreateCommand())
          {
              try
              {
                  OracleDependency OraDep = new OracleDependency(OraComm);
                  OraComm.AddRowid = true;
                  OraComm.CommandText = crawlORACLEServer;
                  OraComm.CommandType = System.Data.CommandType.Text;
                  OraComm.Notification.IsNotifiedOnce = false;
                  OraDep.OnChange += OraDep_OnChange;
      
                  if (OraConn.State == System.Data.ConnectionState.Closed) OraConn.Open();
      
                  dynamic f = await OraComm.ExecuteNonQueryAsync();
      
                  bRet = true;
              }
              catch (OracleNullValueException eN)
              {
                  message = eN.Message;
              }
              catch (OracleTruncateException OT)
              {
                  message = OT.Message;
              }
              catch (OracleTypeException eT)
              {
                  message = eT.Message;
              }
              catch (OracleException ex)
              {
                  message = ex.Message;
              }
              catch (Exception e)
              {
                  message = e.Message;
              }
              finally
              {
                  OraComm.Dispose();
                  OraConn.Dispose();
              }
          }
      }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-20
        • 2014-10-22
        • 1970-01-01
        • 2020-10-11
        • 1970-01-01
        相关资源
        最近更新 更多