为了完整起见,还有一些其他解决方案(在我看来)比依赖 SqlDependency(和 SqlTableDependency)类的解决方案更正统。 SqlDependency 最初旨在使刷新分布式 Web 服务器缓存更容易,因此与将其设计为事件生产者相比,它的构建要求不同。
大致有四个选项,其中一些尚未在此处介绍:
更改跟踪
来源:https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/about-change-tracking-sql-server
更改跟踪是 SQL Server 中的一种轻量级通知机制。基本上,数据库范围的版本号会随着任何数据的每次更改而增加。然后将版本号写入更改跟踪表,其中包含一个位掩码,包括已更改的列的名称。请注意,实际更改不会保留。通知仅包含特定数据实体已更改的信息。此外,由于更改表版本控制是累积的,因此不会保留有关单个项目的更改通知,并且会被较新的通知覆盖。这意味着如果一个实体更改了两次,更改跟踪将只知道最近的更改。
为了在 c# 中捕获这些变化,必须使用轮询。可以轮询更改跟踪表并检查每个更改以查看是否感兴趣。如果感兴趣,则有必要然后直接进入数据以检索当前状态。
变更数据捕获
来源:https://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx
变更数据捕获 (CDC) 比变更跟踪更强大,但成本最高。变更数据捕获将根据监控数据库日志跟踪和通知变更。因此,CDC 可以访问已更改的实际数据,并记录所有单独的更改。
与变化跟踪类似,为了在c#中捕捉这些变化,必须使用轮询。但是,在 CDC 的情况下,轮询信息将包含更改详细信息,因此不必返回数据本身。
触发队列
来源:https://code.msdn.microsoft.com/Service-Broker-Message-e81c4316
此技术依赖于需要通知的表上的触发器。每个更改都会触发一个触发器,触发器会将这些信息写入服务代理队列。然后可以使用 Service Broker 消息处理器(上面链接中的示例)通过 C# 连接队列。
与更改跟踪或 CDC 不同,队列触发器不依赖轮询,从而提供实时事件。
CLR
这是我见过的一种技术,但我不推荐它。任何依赖 CLR 与外部通信的解决方案充其量都是一种 hack。 CLR 旨在通过利用 C# 来更轻松地编写复杂的数据处理代码。它并非旨在连接外部依赖项,如消息传递库。此外,CLR 绑定操作可能会以不可预知的方式在集群环境中中断。
也就是说,设置起来相当简单,因为您需要做的就是向 CLR 注册消息程序集,然后您可以使用触发器或 SQL 作业进行调用。
总结...
让我感到惊讶的是,Microsoft 坚决拒绝解决这个问题。从数据库到代码的事件应该是数据库产品的内置特性。考虑到 Oracle Advanced Queuing 与 ODP.net MessageAvailable 事件相结合,为 C# 提供了可靠的数据库事件处理超过10 年前,这对 MS 来说是可悲的。
这样做的结果是,针对这个问题列出的解决方案都不是很好。它们都存在技术缺陷并且设置成本很高。微软,如果你在听,请解决这个令人遗憾的状况。