有没有一种方法可以在事务记录到日志表中后立即在控制台中显示它们



我有一个表,其中记录了进程,我想创建一个控制台应用程序,一旦消息写入该表,该应用程序就会循环并更新控制台。

最终的结果将是我查看控制台,而不是查询数据库。

我有一个可以提取数据并显示的查询,但我正在寻找最佳实践/更好的解决方案,因为我觉得我的不符合标准

string ConnectionString = "connectionstring here";
string TableName = "table name here";
while (true)
{
SqlConnection myConnection = new SqlConnection(ConnectionString);
myConnection.Open();
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select LogDate, Message from " + TableName + " where convert(date, logdate, 103) = convert(date, getdate(), 103) order by logdate;", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
Console.WriteLine(myReader["LogDate"].ToString() + " -> " +             
myReader["Message"].ToString());
//Thread.Sleep(200);
}
myConnection.Close();
}

我觉得值得一提的三件事:

  • 通过连接不受控制的值来构建动态SQL时要小心。如果TableName的中间有一个空格(或者更糟的是,像TableName; DECLARE @CurrentLogin VARCHAR(100) = SYSTEM_USER; EXEC('DROP LOGIN ' + @CurrentLogin);这样的SQL命令,不执行!),会发生什么。由于您正在动态更改表,因此无法对该查询进行参数化,尽管您可以做一些事情来降低注入风险,例如确保TableName变量少于X个字符(通常20个就足够了),并且不包含空格、分号或关键SQL字(如EXECDROP)
  • 您正在选择和筛选特定的列,因此此查询不能用于大多数表,只能用于具有这些列的表。您应该考虑删除动态表参数,转而使用Switch,只允许查询要查询的表。这将使您的查询受到限制,但更安全
  • 在与常量(getdate())进行比较之前,您的筛选器正在转换表列(logdate),这将使logdate上的索引(如果有的话)不适用。我相信你想查看当天的记录,所以你正在对日期代码103(yyyy-MM-dd)进行比较。您应该避免转换表值,而是使用双过滤器,假设logdateDATETIME。如果logdate的日期不能高于今天,您可以跳过第二次检查:

    WHERE
    logdate >= CONVERT(DATE, GETDATE()) AND
    logdate < CONVERT(DATE, GETDATE() + 1)
    ORDER BY
    logdate
    

最终结果将是我查看控制台而不是查询数据库。

控制台将为您查询数据库,您只是在更改用户界面。

如果你有很多控制台日志,你可以通过datetime进行动态过滤,而不是每次都查询所有的当前日期。因此,每个查询都会带来您查询的最后一个datetime的记录,从而带来所有新的记录。您可以添加一个完整的datetime参数,只检索比前一个更高的记录,并将当前日期时间存储在此变量中。

您可以使用SqlDependency在发生更改时通知您的应用程序,而不是使用pull模型并重复查询数据(即使没有更改)。此链接包含概述和示例。

不过需要注意的一点是,SqlDependency对象是在考虑服务器应用程序的情况下构建的。它并不意味着要推广到许多正在倾听变化的客户。有关其他信息,请参阅此链接。

相关内容

最新更新