轮询MSSQL表的替代方法

时间:2014-10-07 21:49:46

标签: c# sql sql-server polling

我有一个MSSQL表,其中包含我的Windows服务应根据时间戳处理的计划任务,我想知道我有什么选择来轮询这个表

SELECT *
FROM mydb
WHERE SYSUTCDATE() >= timestamp

我可能需要至少每5秒轮询一次表格。基本上我希望我的Windows服务在表中的时间戳设置的时间处理数据。

对我而言,这似乎不是最有效的方式。我已经研究过DML& CLR触发器,我不认为它们会工作,因为它们会在数据发生变化时触发,而不是在时间戳已经过去时触发。想法?


更新2:

我已经意识到将其称为“预定任务”是一个不好的措辞选择,因此我将尝试更详细地描述它。

此项目的目标是根据我们的业务逻辑向人们发送电话通知。一种情况是应该根据内部事件在特定时间打电话给多个人。可以多次呼叫同一个人,具体取决于电话呼叫的应答方式。因此,为了简化操作并消除管理每个电话呼叫状态的复杂性和开销,我认为通过将每个电话呼叫作为表中的条目来预先安排每个电话呼叫是个好主意。应停止通知时,将从表中删除待处理的电话呼叫。这将使Windows服务的设计变得非常简单。它所做的就是根据表格中的时间戳发送通知。


更新1:

消息队列

我还没弄清楚发件人如何在适当的时候将消息放入队列。

的SqlDependency

我使用Detecting Changes with SqlDependency中的示例代码时出现问题。由于某种原因,OnChange事件最初只会被触发,以后什么都不会发生。

更新:我不认为SqlDependency会起作用,因为表中的数据不会改变以使触发器触发。

void Initialization()
{
   // Create a dependency connection.
   SqlDependency.Start(connectionString, queueName);
}

void SomeMethod()
{
   // Assume connection is an open SqlConnection.

   // Create a new SqlCommand object.
   using (SqlCommand command=new SqlCommand(
      "SELECT timestamp,othercolumn FROM mydb WHERE SYSUTCDATE() >= timestamp", 
       connection))
   {

   // Create a dependency and associate it with the SqlCommand.
   SqlDependency dependency=new SqlDependency(command);
   // Maintain the refence in a class member.

   // Subscribe to the SqlDependency event.
   dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);

   // Execute the command.
   using (SqlDataReader reader = command.ExecuteReader())
   {
      // Process the DataReader.
   }
}

1 个答案:

答案 0 :(得分:3)

好的,首先,考虑不要这样做。将所有有用的工作推迟到在数据库中配置的定期任务是一个脆弱的设计,当有人误配置事物时很容易破坏(很容易做到,因为你需要非常高级的触发器来检查计划的一致性),并且它也倾向于当任务实际上具有隐藏的依赖关系时,创建一个难以理解的系统(如果A没有在B之前运行一段时间,那么东西会破坏,那种事情)。资料来源:在三个不同的公司和三个不同的平台/技术中有三个这样的系统的个人经验,并且不知何故他们都遇到了同样的问题,所以显然它是一件事。考虑使用配置文件将您想要安排的内容写为普通旧代码。当然,它不会像通用一样,但是必须维护它的人会感谢你,特别是当他们的需求变得更加复杂时。

SqlDependency相当变幻无常,即使您确实拥有支持的查询,也不易使用。在您的情况下,正如您所注意到的那样,它不起作用,因为除非数据实际发生变化,否则数据库引擎不会发布通知 - 查询结果的变化并不重要时间流逝。正如尼克指出的那样,每5秒轮询一次数据库通常就可以了。如果您在mydb.timestamp上创建了一个索引,那么这会产生可忽略不计的负载(并且您创建此索引非常重要,因为每隔5秒执行一次表扫描确定)。

唯一的反对意见是延迟:如果对计划的任何更新必须早于每5秒发生一次,则轮询不够好。在这种情况下,您可以使用Service Broker并在事件发生变化时(可能来自触发器)向队列发布通知。实际上,SqlDependency使用相同的方法,因此您可以创建对SELECT * FROM table的依赖关系,以便在表中任何任何更改时获得通知,然后执行实际的查询,以获得你需要的东西(可能发现那里什么都没有)。但请注意:获取正确的代码而不会因多次快速更新或连接中断而感到困惑并非易事,而且可能不值得,而不是仅定期重新加载。