我有一个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.
   }
}

最佳答案

好的,首先,请考虑完全不执行此操作。将所有有用的工作交给数据库中配置的定期任务是一个脆弱的设计,当有人错误地配置事物时,它很容易被破坏(易于执行,因为您需要相当先进的触发器来检查计划一致性),而且它还倾向于当任务实际上具有隐藏的依赖关系时,创建一个无法理解的系统(如果A在B之前还没有运行一段时间,那么东西就会中断,诸如此类)。资料来源:在三个不同的公司和三个不同的平台/技术中使用三个这样的系统的个人经验,并且它们都以某种方式遭受相同的问题,所以显然这是一件事情。考虑仅使用配置文件将您要调度的内容编写为简单的旧代码。当然,它不会那么通用,但是必须维护它的人会感谢您,尤其是当他们的需求变得越来越复杂时。
SqlDependency非常善变,即使您确实有受支持的查询,也不容易很好地使用。如您所知,您的情况不起作用,因为除非数据实际更改,否则数据库引擎将不会发布通知-随时间的流逝查询的结果也将更改。正如Nick所指出的,通常每5秒轮询一次数据库就可以了。如果您在mydb.timestamp上创建了索引,则产生的负载可以忽略不计(并且创建索引非常重要,因为每5秒执行一次表扫描是不可行的)。

唯一的异议是延迟:如果计划表的任何更新必须早于每5秒一次,则轮询还不够好。在这种情况下,您可以使用Service Broker并在发生更改的瞬间(可能是来自触发器)将通知发布到队列中。实际上,SqlDependency在幕后使用了相同的方法,因此您可以对SELECT * FROM table创建一个依赖项,以在表中发生任何更改时获取通知,然后执行实际查询以获取所需的内容(可能发现什么都没有)。但是要当心:正确地获取代码而不会因多次快速更新或连接中断而感到困惑,这并非微不足道,而且可能不值得,而不是仅仅定期重新加载。

关于c# - 轮询MSSQL表的替代方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26245903/

10-12 23:20