SQL CLR触发器能做到这一点吗?或者有更好的方法吗?

7
我想编写一个服务(可能是用C#),用于监视数据库表。当插入记录时,我希望该服务能够获取新插入的数据,并对其执行一些复杂的业务逻辑(TSQL无法实现)。
一种选择是让该服务定期检查表格,以查看是否插入了新记录。但这种方式存在问题,即我希望服务能够在插入发生后立即知道它们的情况,而且不会影响数据库性能。
经过一些研究,似乎编写CLR触发器可以完成此任务。我可以用C#编写触发器,在插入发生时触发它,然后将新插入的数据发送到Windows或WCF服务。
你认为这样使用SQL CLR触发器好吗(或者可行吗)?
还有其他实现方法吗?
6个回答

6

建议将后处理与插入过程分离:

在插入触发器中,将记录的主键添加到队列表中。

在单独的服务中,从队列表中读取并执行复杂操作。完成后,标记记录为已处理(包括错误/状态信息),或从队列中删除记录。


正是我即将建议的。这将是安全的事务,会将已处理和未处理的记录持久化到一个不会影响主应用程序表的表中。对此解决方案点赞! - evilhomer
2
使用SQL Server Service Broker。 - Chris KL
好主意,除了你会失去所有已更改的内容的痕迹(即DELETED表的内容,在触发器执行期间才可用)。这取决于你需要什么,我想。 - David Catriel

3
您所描述的内容有时被称为作业队列或消息队列。您可以通过搜索找到几个使用数据库表(以及其他技术)来执行此操作的线程。
我认为使用触发器做这样的事情是不恰当的数据库功能使用,因为无论如何都容易出现问题。触发器最好用于低开销的数据库结构功能(例如细粒度引用完整性检查),并且需要轻量级和同步。虽然可以完成此操作,但可能不是一个好主意。

2

我建议在表上设置一个触发器,调用SQL Server Service Broker,然后(异步地)执行一个CLR存储过程,在不同的线程中完成所有工作。


同意。.net代码甚至不必是clr存储过程——它可以从另一个进程中消耗队列内容。 - Sean Reilly

1

我有一个服务,每分钟轮询数据库,它不会导致太多性能问题,而且是一种干净的解决方案。此外,如果您的服务或其他WCF端点不存在,您的触发器将失败或丢失,您以后仍然需要轮询。


1
我不建议使用CLR触发器或任何类型的触发器来处理此问题。这样会导致严重的可维护性和潜在的锁定问题。(如果您不关心插入后的@@identity并且永远不会锁定审核/队列表,则可以接受非常简单的触发器将内容放入审核/队列表中)
相反,您应该从应用程序/ORM中触发将内容插入队列表,并定期处理此队列。这可以通过在ORM中具有事务或启动存储过程来完成,该存储过程开始事务提交更改并原子地进行审核/队列。(在这里要小心锁定)
如果您需要立即采取行动,请查看生成作业以在对表进行插入/更新/删除后清除队列。
还要确保每分钟左右再次检查队列,以防未正确启动后台进程。如果是Web应用程序并且要避免生成线程,则可以与后台进程通信以清除队列。

-1
为什么不在存储过程中实现插入,并在插入之后在存储过程中处理业务逻辑呢?这有何难度,不能使用T-SQL编写吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接