异步?
如果您每次都无法确定是否打开/关闭连接,那么调用它在某种程度上是等效的(请原谅我,我知道这不是很准确)BeginExecuteNonQuery
(这是 MARS 之前使用的方法)。实际上,每个请求都是同步的,但是,如果您以 5 毫秒的间隔记录一些内容,您无法确定 SQL Server 将服务该请求的顺序(这里的数据库人员会考虑IDENTITY 列的旧问题)。
时间戳
那么解决方案应该是使用 TimeStamp 列并根据该列对结果进行排序(写入顺序无关紧要)。这是完美的解决方案(正如其他答案所指出的那样,不要忘记使用正确的数据类型来存储数据)。
如何获得实际时间?您可以在客户端(如您的示例中)使用DateTime.Now
函数或在服务器端使用SYSDATETIME
(如@PetrAbdulin 指出的那样)。如果您不需要高分辨率,这是一个完美的解决方案。
精确
这两个函数都依赖于 Windows 系统计时器,并且它的分辨率不超过 10 毫秒(那么,如果你真的需要 5 毫秒的粒度,你应该避免它们)。
在 MSDN 上,您可以读到Windows NT 上的DateTime.Now的分辨率为 10 毫秒,SYSDATETIME调用GetSystemTimeAsFileTime,该FILETIME
结构的精度为 100 毫秒,但计时器本身没有被授予实现该结果!!!在某些情况下,您甚至可能会得到 1 毫秒的滴答声,但它根本不可靠。在有关秒表计时器的文档中,您可以阅读:
秒表类使用的计时器取决于系统硬件和操作系统。如果秒表计时器基于高分辨率性能计数器,则 IsHighResolution 为真。否则,IsHighResolution 为 false,表示秒表计时器是基于系统计时器的。
这是什么意思?系统计时器永远不会被授予高分辨率(不要被用于存储时间的结构的精度混淆)。
这可能是一个问题,这取决于你将使用你的日志。如果您必须在备份期间记录从一个文件夹复制到另一个文件夹的文件列表,那么您可能不需要这种精确度。如果您的日志可能用于合法的东西(是的,我知道它们不应该具有任何合法价值)或调试一个微妙的线程问题,那么您将需要它。
解决方案
如果您需要一个高分辨率计时器(并且,在 Windows 上,您可以将任何小于 10 毫秒的时间视为高分辨率),您必须处理性能计数器。看看这篇关于时间的好文章。当然,您不需要所有这些东西,但它指出了问题所在。
在 .NET 中,您可以使用DateTime.Now
a StopWatch
(检查IsHighResolution
属性)。在 SO 上阅读这篇关于使用StopWatch
提高DateTime.Now
.
常见错误
首先不要将用于存储时间的数据类型的精度与定时器的分辨率混淆。如果您将该值存储在低分辨率字段中,那么您的计时器有多精确并不重要,但使用高分辨率字段不会将您的粗略计时器转换为高分辨率计时器。
此外,您不应该使用本地时间作为时间戳,当系统时间因夏令时而改变时,您会混淆您的日志。想一想:
00:00 02:00 02:01 03:00 02:00
日志 #1 #2 #3 #4
系统时间-1
现在你什么时候阅读你的日志,你会得到这个顺序:1、2、4、3。出于这个原因,你永远不应该使用DateTime.Now
andSYSDATETIME
对于你的日志,你应该总是更喜欢DateTime.UtcNow
andSYSUTCDATETIME
函数(而且性能DateTime.UtcNow
有点更好的)。