c# - 轮询 MSSQL 表的替代方法

标签 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.
   }
}

最佳答案

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

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

唯一的反对意见是延迟:如果对计划的任何更新必须在每 5 秒内发生一次,轮询就不够好。在这种情况下,您可以使用 Service Broker 并在发生某些变化(可能来自触发器)时立即向队列发布通知。事实上,SqlDependency 在幕后使用相同的方法,因此您可以创建对 SELECT * FROM table 的依赖,以便在任何 时获得通知更改表,然后执行实际查询以获取所需内容(可能发现什么都没有)。但是请注意:在不被多次快速更新或连接中断弄糊涂的情况下获得正确的代码并不是微不足道的,而且可能不值得这样做,而不是定期重新加载。

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

相关文章:

c# - 如何使用正则表达式将字符串 `{{key.value}}` 拆分为两个字符串 `key` 和 `value` ?

c# - 仅从 Dapper connection.Query<T>(sql) 返回某些列/字段

c# - 从 Single 到 Decimal 的显式转换导致不同的位表示

mysql - 将 SQL 结果格式化为总和

sql - 使用 XML 数据类型读取存储在 SQL Server 2008 R2 中的 XML 文档

c# - 将 Flash 转换为 C# 时出错

SQL Server按不同列过滤时查询速度存在差异

php - htmlspecialchars 是否足以防止对用单引号引起来的变量进行 SQL 注入(inject)?

sql - 左外部连接比没有连接返回更多的行

mysql - 使用 select 语句更新动态列值