当前位置: 首页 > 编程语言 > C#

如何通知WindowsService(c#)DBtablechanges(sql2005)?share

时间:2023-04-10 20:00:49 C#

如何通知Windows服务(c#)数据库表更改(sql2005)?我在SQL2005数据库中有一个负载很重的表(许多插入/更新/删除)。我想尽可能接近实时地对所有这些更改进行一些后处理(异步以便不以任何方式锁定表)。我已经查看了许多可能的解决方案,但似乎无法找到一个感觉合适的简洁解决方案。后处理的类型也相当繁重,以至于Windows侦听器服务实际上将处理交给了很多机器。然而,应用程序的这一部分已经启动并运行,完全异步,并不是说我需要帮助——我只是想提一下这只是因为它影响了设计决策,因为我们不能仅仅将一些CLR对象加载到数据库中来完成加工。所以,简单的问题仍然存在:表中的数据发生变化,我想在远程服务器上用c#代码进行一些处理。目前我们已经想出了使用执行“xp_cmdshell”的sql触发器来启动一个exe,该exe引发Windows服务正在侦听的事件。感觉很糟糕。然而,我在网上看到的其他解决方案也相当复杂。例如,设置SQLCacheDependancy还需要设置ServiceBroker。另一种可能的解决方案是使用CLR触发器,它可以调用Web服务,但网上有很多警告说这是一种糟糕的方法,尤其是在性能至关重要的情况下。理想情况下,我们不会对表单进行更改,而是拦截我们应用程序中的调用并从那里通知服务,不幸的是,我们还有一些遗留应用程序也在更改数据并监视表单是唯一的集中位置就是这一刻。任何帮助是极大的赞赏。简介:您确实没有太多方法可以检测SQL2005中的更改。您已经列出了其中的大部分方法。查询通知。这是SqlDependency及其衍生产品背后的技术,您可以阅读有关TheMysteriousNotification的更多详细信息。但QN旨在使结果无效,而不是主动通知更改。你只知道表变了,不知道变了什么。在繁忙的系统上,这将不起作用,因为通知会不断发生。日志阅读。这是事务复制所使用的,也是检测更改的侵入性最小的方法。不幸的是,仅适用于内部组件。即使你设法理解日志格式,问题是你需要引擎支持将日志标记为“正在使用”,直到你阅读它,否则它可能会被覆盖。只有事务复制才能执行这种特殊标记。数据比较。依靠时间戳列来检测变化。也是基于拉取的,非常激进并且检测删除有问题。应用层。这是理论上的最佳选择,除非数据更改超出应用程序的范围,在这种情况下它会崩溃。实际上,总会有应用范围之外的变化。扳机。最终,这是唯一可行的选择。所有基于触发器的更改机制都以相同的方式工作,它们将更改通知排队到监视队列的组件。总是建议进行紧密耦合的同步通知(通过xp_cmdshell、xp_olecreate、CLR、通知WCF,随便你怎么说),但所有这些方案在实践中都失败了,因为它们存在根本性缺陷:-它们没有考虑事务一致性和回滚-它们引入了可用性依赖性(OLTP系统无法继续,除非被通知的组件在线)-它们执行得非常糟糕,因为每个DML操作都必须等待某种形式的RPC调用完成如果触发器实际上没有主动通知侦听器,但是仅排队通知,那么监视通知队列就会出现问题(当我说“队列”时,我指的是充当队列的任何表)。监控意味着在队列中拉取新条目,这意味着适当地平衡检查频率与变化的负载,并对负载峰值做出反应。这一点都不简单,其实很难。但是,SQLServer中有一条语句具有阻塞语义,在更改可用之前不需要被拉出:WAITFOR(RECEIVE)。这意味着服务代理。您在您的帖子中多次提到SSB,但由于存在很大的未知数,您害怕部署SSB是完全正确的。但事实是,它是迄今为止您描述的任务的最佳选择。您不必部署一个完整的SSB架构,在该架构中,通知会一直传递到远程服务(无论如何都需要远程SQL实例,甚至是Express实例)。您需要做的共同点是,将检测到更改(DML触发器)的时刻与发送通知的时刻(更改提交后)解耦。为此,您需要的是本地SSB队列和服务。在触发器中,您向本地服务发送更改通知。在原始DML事务提交后,服务进程激活并传递通知,例如使用CLR。您可以在异步T-SQL中看到与此类似的示例。如果你走这条路,你需要学习一些技巧来实现高吞吐量,你必须了解SSB中消息有序传递的概念。我建议您阅读这些链接:SQL2008显然为检测更改的方法添加了新选项:ChangeDataCapture和ChangeTracking。我强调“显然”是因为它们并不是真正的新技术。CDC使用基于现有事务复制机制的日志读取器。CT使用触发器,与现有的Merge复制机制非常相似。它们都适用于需要同步的偶尔连接的系统,因此不适合实时更改通知。它们可以填充更改表,但您可以使用任务来监视这些表的更改,这完全取决于您从哪里开始。这可以通过多种方式完成。下面的方法很简单,因为您不想使用CLR触发器和sqlcmd选项。编辑:我认为MicrosoftSynchronizationServiceforADO.Net可以为您工作。查看下面的链接。它可能对您有帮助在类似的情况下,我们使用CLR触发器将消息写入队列(MSMQ)。用C#编写的服务正在监视队列并进行后处理。在我们的例子中,它完全在同一台服务器上完成,但您可以将这些消息直接发送到另一台机器上的远程队列,完全绕过“本地侦听器”。从触发器调用的代码如下所示:publicstaticvoidSendMsmqMessage(stringqueueName,stringdata){//根据输入参数定义队列路径。字符串QueuePath=String.Format(".\private$\{0}",queueName);尝试{如果(!MessageQueue.Exists(QueuePath))MessageQueue.Create(QueuePath);//以发送访问模式打开队列MessageQueueMSMQueue=newMessageQueue(QueuePath,QueueAccessMode.Send);//定义队列消息格式并创建消息BinaryMessageFormatterMessageFormatter=newBinaryMessageFormatter();消息MSMQMessage=newMessage(data,MessageFormatter);MSMQueue.发送(MSMQMessage);}catch(Exceptionx){//异步日志记录:必须尽快从触发器返回System.Threading.ThreadPool.QueueUserWorkItem(newWaitCallback(LogException),x);既然你说那个表上运行了很多插件,那么批处理可能更合适。为什么只创建一个计划的作业来处理由标志列标识的新数据并以块的形式处理数据?使用典型触发器在数据库上触发CLR。这个CLR会只使用Win32_Process类远程启动程序:http://motevich.blogspot.com/2007/11/execute-program-on-remote-computer.html以上是C#学习教程:HowtonotifyDBtable更改(sql2005)windows服务(c#)?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: