设置
我创建了一个面向.NET 4.7.2的控制台应用程序,并安装了NuGet软件包Oracle.ManagedDataAccess版本12.2.1100(最新/当前),该软件包设置了一个带有2个查询的依赖项,以监控对{{{ 1}},两个查询都有不同的WHERE子句。
我正在连接的Oracle数据库服务器在localhost上运行,版本为12.2.0.1.0。
在侦听通知的控制台应用程序旁边,我使用Oracle SQL Developer(v18.1.0.095)实际插入或更新记录到MYTABLE以强制通知。
代码
MYTABLE
行为
只要在一个事务中触发多个命令依赖项,我就会在通知中获得两倍的事件行,并且无法再区分触发它的queryid。
在一个交易中运行此查询:
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();
}
输出:
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
时,我首先获得4行UPDATE
+ INSERT
对于第二个QueryId(64),QueryId(63)和UPDATE
+ INSERT
,所以现在我可以区分它们。
将命令依赖关系分隔为多个UPDATE
类甚至多个连接会导致相同的结果。
我想知道是否有人知道这里发生了什么?
答案 0 :(得分:0)
也许将相同的 OracleDependency 实例与两个 OracleCommand 一起使用会导致这种现象。
AddCommandDependency 的Oracle docs中的注释部分说这是可能的,但它似乎不是默认配置。>
我建议使用两个单独的 OracleDependency 实例。我们不知道如何在内部完成两个查询的聚合,但是我猜测ODP.NET可能会使用“保证”模式不支持的语法以某种方式将两个查询聚合为一个。
这可能导致通知使用“尽力而为”模式,该模式在文档中被声明为容易误报。
使用ODP.NET时似乎没有一种知道使用哪种模式的方法,但是我猜想该模式是从查询中自动检测到的,并且记录了每种模式的查询约束{{3} }。
答案 1 :(得分:0)
尝试检查 OracleDependency 的 QueryBasedNotification。
默认情况下,此属性为 true。 ODP.NET 开发人员可以在行级别注册他们的查询,而不仅仅是对象 级别,从适用于 .NET 版本 11.1 的 Oracle Data Provider 和 Oracle Database 开始 11g 版本 1(11.1)。应用程序仅在选定行或 rows change.Query - 基于通知为开发人员提供了更多的使用粒度 客户端缓存数据,因为它们可以更具体地说明什么改变了 需要通知应用程序