如何将[Log Content 0]中的fn_dblog详细信息中的8字节日期时间转换为C#DateTime对象?

问题描述

删除了最近插入的一行数据。 我正在尝试使用fn_dblog()“未记录”的系统函数来检索该数据,而不是还原并前滚此巨大数据库的第二个副本以检索插入的数据。 使用描述(可在此处找到https://sqlfascination.com/2010/02/03/how-do-you-decode-a-simple-entry-in-the-transaction-log-part-1/

fn_dblog()返回[Log Content 0]列的内容

,我已经从日志文件中成功检索了我插入(然后删除)的数据。在为固定宽度列数据保留的此二进制数据部分中,我发现sql DateTime列值占用8个字节。我正在使用BitConverter.ToInt64或BitConverter.ToInt32(适合Int或BigInt值)在.NET程序中处理二进制数据

我已经设法检索了我需要的所有插入列值,除了datetime列...

我不清楚如何将sql DateTime列的8个字节解释为C#DateTime对象。如果有帮助,则下面是从特定日期时间的事务日志数据中检索到的8个字节的日期时间的十六进制和Int64版本的示例。

DateTime(大约7/31/2020)二进制:0xF030660009AC0000(字节序颠倒为0x0000AC09006630F0)

作为Int64:189154661380804

有什么建议吗?这是日期的内部sql Server表示形式,我不确定在哪里可以找到文档...

解决方法

我终于找到了答案:存储为VARBINARY的SQL DateTime(类似于我从事务日志中读取的字节)包含两个整数。第一个是日期部分-自1900年1月1日以来的天数。较早的日期将为负。

第二个整数是自午夜以来的毫秒数除以3.33333333。

因为字节存储为长整数,并且相反,所以缓冲区8个字节中的前4个字节是分钟,第二个是日期。

这是我用来获取日期的代码段。我一次遍历固定长度的字段,跟踪字节数组中的当前偏移量... 变量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);