设定

我已经创建了一个针对.NET 4.7.2的控制台应用程序,并安装了NuGet软件包Oracle.ManagedDataAccess版本12.2.1100(最新/最新),该软件包设置了2个查询的依赖项,以监视对MYTABLE所做的更改,两个查询都具有一个不同的WHERE条款。

我要连接的Oracle数据库服务器在localhost上运行,版本为12.2.0.1.0。

在侦听通知的控制台应用程序旁边,我正在使用Oracle SQL Developer(v18.1.0.095)实际将记录插入或更新为MYTABLE,以便强制发出通知。



using (var connection = new OracleConnection("Data Source=//localhost:1521/ORCL;Persist Security Info=True;User ID=SYSTEM;Password=password"))
{
    OracleDependency.Port = 3005;

    var dependency = new OracleDependency();
    dependency.OnChange += (sender, eventArgs) =>
    {
        Console.WriteLine($"Change count: {eventArgs.Details.Rows.Count}");

        // Columns in row: string ResourceName, int Info, string Rowid, long QueryId
        foreach (DataRow row in eventArgs.Details.Rows)
        {
            var resourceName = (string)row["ResourceName"];
            var info = (OracleNotificationInfo)row["Info"];
            var rowId = (string)row["rowid"];
            var queryId = (long)row["QueryId"];

            Console.WriteLine($"{queryId} {info} {rowId} {resourceName}");
        }
    };

    connection.Open();

    var command1 = new OracleCommand("SELECT * FROM MYTABLE WHERE NAME = 'N1'", connection);
    dependency.AddCommandDependency(command1);
    command1.Notification.IsNotifiedOnce = false;
    command1.AddRowid = true;
    command1.ExecuteNonQuery();

    var command2 = new OracleCommand("SELECT * FROM MYTABLE WHERE NAME = 'N2'", connection);
    dependency.AddCommandDependency(command2);
    command2.Notification.IsNotifiedOnce = false;
    command2.AddRowid = true;
    command2.ExecuteNonQuery();

    Console.ReadKey();
}


行为

一旦在一个事务中触发多个命令依赖关系,通知中的事件行就会增加一倍,并且无法再区分触发它的queryid。

在一个事务中运行此查询:

INSERT INTO MYTABLE (NAME) VALUES ('N1');


输出:

Change count: 1
63 Insert AAAR6CAABAAALohABJ SYSTEM.MYTABLE


在一个事务中运行此查询:

INSERT INTO MYTABLE (NAME) VALUES ('N2');


输出:

Change count: 1
64 Insert AAAR6CAABAAALohABK SYSTEM.MYTABLE


但是,在一个事务中运行此查询时:

INSERT INTO MYTABLE (NAME) VALUES ('N1');
INSERT INTO MYTABLE (NAME) VALUES ('N2');


我得到以下输出:

Change count: 4
63 Insert AAAR6CAABAAALohABH SYSTEM.MYTABLE
63 Insert AAAR6CAABAAALohABI SYSTEM.MYTABLE
64 Insert AAAR6CAABAAALohABH SYSTEM.MYTABLE
64 Insert AAAR6CAABAAALohABI SYSTEM.MYTABLE


虽然我期望:

Change count: 2
63 Insert AAAR6CAABAAALohABH SYSTEM.MYTABLE
64 Insert AAAR6CAABAAALohABI SYSTEM.MYTABLE


另外,当我执行触发第一个命令的INSERT和触发第二个命令的UPDATE时,对于第一个QueryId(63)和INSERT + UPDATE + INSERT >作为第二个QueryId(64),因此现在我可以将它们区分开。

在多个UPDATE类或什至多个连接上分隔命令依赖项会导致相同的结果。

我想知道是否有人知道这里发生了什么?

最佳答案

也许将相同的OracleDependency实例与两个OracleCommand一起使用会导致此行为。

Oracle docs中AddCommandDependency的备注部分说这是可能的,但它似乎不是默认配置。

我建议使用两个单独的OracleDependency实例。我们不知道如何在内部完成两个查询的聚合,但是我猜测ODP.NET可能会使用“保证”模式不支持的语法以某种方式将两个查询聚合为一个。

这可能会导致通知使用“尽力而为”模式,该模式在文档中被声明为容易出现误报。

似乎没有办法知道在使用ODP.NET时使用哪种模式,但是我猜想该模式是从查询中自动检测到的,并且每种模式的查询约束都记录在here中。

关于c# - Oracle变更通知包含无效操作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50875634/

10-17 02:26