如何将 [Log Content 0] 中 fn_dblog() 详细信息中的 8 字节日期时间转换为 C# DateTime 对象?
Posted
技术标签:
【中文标题】如何将 [Log Content 0] 中 fn_dblog() 详细信息中的 8 字节日期时间转换为 C# DateTime 对象?【英文标题】:How to convert 8 byte datetime from fn_dblog() details in [Log Content 0] into a C# DateTime object? 【发布时间】:2021-01-08 02:33:36 【问题描述】:我删除了最近插入的一行数据。 我没有恢复和前滚这个巨大数据库的第二个副本来检索插入的数据,而是尝试使用 fn_dblog()“未记录”系统函数来检索它。 使用描述(在此处找到:https://sqlfascination.com/2010/02/03/how-do-you-decode-a-simple-entry-in-the-transaction-log-part-1/)
在 [Log Content 0] 列 fn_dblog() 返回的内容中,我成功地从日志文件中检索了我插入的(以及后来删除的)数据。在为固定宽度列数据保留的二进制数据部分中,我发现 SQL DateTime 列值占用 8 个字节。我在 .NET 程序中处理二进制数据,使用适用于 Int 或 BigInt 值的 BitConverter.ToInt64 或 BitConverter.ToInt32
我已经成功检索到除日期时间列之外的所有插入的列值...
我不清楚如何将 SQL DateTime 列的 8 个字节解释为 C# DateTime 对象。如果有帮助,下面是从特定日期时间的事务日志数据中检索到的 8 字节日期时间的示例 hex 和 Int64 版本。
二进制日期时间(2020 年 7 月 31 日左右):0xF030660009AC0000(字节序反转:0x0000AC09006630F0)
作为 Int64:189154661380804
有什么建议吗?这是日期的内部 SQL Server 表示,我不确定在哪里可以找到文档...
【问题讨论】:
【参考方案1】:我终于找到了答案:存储为 VARBINARY 的 SQL DateTime(类似于我从事务日志中读取的字节)包含两个整数。第一个是日期部分 - 自 1900 年 1 月 1 日以来的天数。对于较早的日期,它将是负数。
第二个整数是自午夜以来的毫秒数,除以 3.33333333。
由于字节存储为long和反向,缓冲区中8个字节的前4个字节是分钟,第二个是日期。
所以这是我用来获取日期的代码 sn-p。我一次遍历一个固定长度字段,跟踪字节数组中的当前偏移量...... 变量 ba 是 [Log Content 0] 列中字节的字节数组。
int TimeInt;
int DateInt;
DateTime tmpDt;
//initialize the starting point for datetime - 1/1/1900
tmpDt = new DateTime(1900, 1, 1);
// get the time portion of the SQL DateTime
TimeInt = BitConverter.ToInt32(ba, currOffset);
currOffset += 4;
// get the date portion of the SQL DateTime
DateInt = BitConverter.ToInt32(ba, currOffset);
currOffset += 4;
// Add the number of days since 1/1/1900
tmpDt = tmpDt.AddDays(DateInt);
// Add the number of milliseconds since midnight
tmpDt = tmpDt.AddMilliseconds(TimeInt * 3.3333333);
【讨论】:
以上是关于如何将 [Log Content 0] 中 fn_dblog() 详细信息中的 8 字节日期时间转换为 C# DateTime 对象?的主要内容,如果未能解决你的问题,请参考以下文章