oracle官方无原生continuous query功能;.net 6中continuous query notification(cqn)实为change notification机制,仅通知查询结果集失效,不提供dml类型、字段变更值或行级详情,依赖aq且触发条件苛刻。

Oracle 官方没有叫 Continuous Query 的原生实时流式查询功能,.NET 6 中所谓 “Continuous Query Notification” 实际就是 Oracle 的 Change Notification(旧称 DCN),现统一叫 Continuous Query Notification(CQN)。它不是数据库变更的实时捕获(CDC),而是一种“结果集失效通知”机制——只告诉你“你查的那几行可能变了”,不告诉你谁改了、怎么改、改前改后是什么。
为什么 OracleDependency 在 .NET 6 里经常不触发或报错
根本原因在于 CQN 依赖 Oracle Advanced Queuing(AQ)和数据库端的事件通知通道,但它的触发条件极其苛刻:
-
OracleDependency注册的 SQL 必须是单表查询,不能有JOIN、子查询、聚合函数、DISTINCT、ORDER BY(除非带主键) - 目标表必须启用
ENABLE TABLE FOR CHANGE NOTIFICATION,且用户需被授予CHANGE NOTIFICATION权限 - 连接字符串必须开启
HA Events=true,否则底层 AQ 通道无法建立 - 客户端机器的防火墙必须放行 Oracle 数据库通知使用的随机端口(通常为 1024–65535 范围),否则通知包被丢弃,无任何错误提示
- 注册后若数据库重启、归档日志切换或监听器重载,依赖会静默失效,
OnChange事件再也不会触发
在 .NET 6 中正确注册一个 CQN 依赖的最小代码片段
以下代码假设你已确认 HR.EMPLOYEES 表已执行过 ALTER TABLE hr.employees ENABLE CHANGE NOTIFICATION,且当前用户有权限:
using Oracle.ManagedDataAccess.Client;
string connStr = "User Id=hr;Password=hr;Data Source=orcl;HA Events=true;";
using var conn = new OracleConnection(connStr);
conn.Open();
string sql = "SELECT employee_id, first_name, last_name FROM hr.employees WHERE department_id = :deptId";
using var cmd = new OracleCommand(sql, conn);
cmd.Parameters.Add(new OracleParameter("deptId", 10));
var dep = new OracleDependency(cmd); // 注意:必须在 cmd 执行前创建
dep.OnChange += (sender, args) =>
{
Console.WriteLine($"Invalidation reason: {args.Type}"); // 通常是 Invalidated
// 此处应刷新缓存,而非重试注册
};
cmd.ExecuteNonQuery(); // 必须执行一次,才能真正注册监听
// 注意:conn 不能在此处 Close(),否则依赖立即失效
关键点:OracleDependency 对象生命周期必须长于命令执行,且连接不能提前关闭;OnChanges 触发后不会自动重注册,需手动再次调用 cmd.ExecuteNonQuery() 才能继续监听下一轮变化。
CQN 不适合哪些场景
如果你需要以下任意一种能力,CQN 就不是解法,该换 LogMiner 或 GoldenGate:
- 获取原始 DML 类型(
INSERT/UPDATE/DELETE)和具体字段变更值 - 捕获未提交事务的中间状态(CQN 只在事务提交后通知)
- 跨多表关联查询的结果一致性监控(比如订单+订单项联合视图)
- 低延迟要求(实际延迟常达数秒到分钟级,取决于 AQ 队列消费速度)
- 无主键或无合适过滤条件的表(CQN 无法定位哪行失效,只能整个结果集标记为 invalid)
最易被忽略的一点:CQN 的通知内容里 不包含任何变更数据,只有 args.Type、args.Source 和 args.Info 这几个枚举字段。你永远拿不到 old_value / new_value,只能靠自己重新查一遍——这正是它和真正 CDC 的本质分水岭。











