如何在.NET中比较SQL时间戳?

12

我已经映射了Entity Framework实体。SQL Server 2008中的每个表都包含Timestamp列,它被映射为字节数组。数组的长度始终为8。

现在我需要在.NET中比较时间戳值。我想到了两个解决方案,但我不知道哪一个更好?

  • 将其作为数组进行比较。当第一对字节不同时返回false。
  • 将字节数组转换为long,然后进行比较。

哪种解决方案更好?还是有其他的解决方案吗?

2个回答

11

我们通过将它们作为字节数组进行比较来实现。这对我们来说很有效。


9

MS SQL Server的时间戳数据类型在语义上等同于二进制(8)(如果不可为空)或varbinary(8)(如果可为空)。因此,将它们作为字节数组进行比较。

更不用说转换为long存在开销。您可以编写一些不安全的代码来获取字节数组的地址,将其强制转换为long指针并将其解引用为long,但要安全地执行此操作意味着将它们固定在内存中并编写一堆丑陋的代码以执行基本简单的操作(而且可能不比使用BitConverter快)。

如果性能真的很关键,最快的方法是通过P/Invoke使用标准C库的memcmp()函数进行比较:

using System;
using System.Runtime.InteropServices;

namespace TestDrive
{
    class Program
    {
        static void Main()
        {
            byte[] a = { 1,2,3,4,5,6,7,8} ;
            byte[] b = { 1,2,3,4,5,0,7,8} ;
            byte[] c = { 1,2,3,4,5,6,7,8} ;
            bool isMatch ;

            isMatch = TimestampCompare( a , b ) ; // returns false
            isMatch = TimestampCompare( a , c ) ; // returns true

            return ;
        }

        [DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
        static extern int memcmp(byte[] x , byte[] y , UIntPtr count ) ;

        static unsafe bool TimestampCompare( byte[] x , byte[] y )
        {
            const int LEN = 8 ;
            UIntPtr   cnt = new UIntPtr( (uint) LEN ) ;

            // check for reference equality
            if ( x == y ) return true ;

            if ( x == null || x.Length != LEN || y == null || y.Length != LEN )
            {
                throw new ArgumentException() ;
            }

            return ( memcmp(  x ,  y , cnt ) == 0 ? true : false ) ;
        }

    }

}

一个老派的C程序员 B^) - Nicholas Carey
@Nicholas +1,这很好,但我想避免不安全的代码。 - Ladislav Mrnka
x == y” 应该改为 “*Object.ReferenceEquals(x, y)*”,以确保类型没有重载操作符。 - Pauli Østerø
除非您有一种秘密的方法来对密封类System.Byte或特殊类System.Array进行子类型化,否则不可能。 - Nicholas Carey
4
除非你使用将数据转换的标准方法,而不是重新发明轮子-- BitConverter.ToInt64(binary.ToArray(), 0),是的,它只需要一行代码。 - greenoldman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接