如何在C#或Linq中比较大于或小于运算符值的两个字节数组?

Dil*_*165 5 c# linq sql-server arrays timestamp

我在Code TimeStamps的Code First Entity Framework中有一个字节数组,映射如下:

 [Column(TypeName = "timestamp")]
 [MaxLength(8)]
 [Timestamp]
 public byte[] TimeStamps { get; set; }
Run Code Online (Sandbox Code Playgroud)

上述属性等于C#中的SQL服务器"timestamp"数据类型.

在SQL服务器中,我可以轻松比较"时间戳",如下所示......

SELECT * FROM tableName WHERE timestampsColumnName > 0x000000000017C1A2
Run Code Online (Sandbox Code Playgroud)

我希望在C#或Linq Query中实现同样的功能.在这里,我编写了我的Linq查询,该查询无法正常工作.

 byte[] lastTimeStamp = someByteArrayValue;
 lstCostCenter.Where(p => p.TimeStamps > lastTimeStamp);
Run Code Online (Sandbox Code Playgroud)

我也尝试过BitConverter比较一个双字节数组,这个数组也无法正常工作......

 lstCostCenter.Where(p => BitConverter.ToInt64(p.TimeStamps, 0) > BitConverter.ToInt64(lastTimeStamp, 0));
Run Code Online (Sandbox Code Playgroud)

如何比较C#或Linq Query中的字节数组.

注意 - 我只是不想比较两个数组,就像使用SequenceEqual或任何其他方法只是比较并返回true或false.我希望Linq查询中的比较大于>或小于<运算符,它提供了正确的数据,如SQL Server查询.

Evk*_*Evk 11

一种方法是使用IStructuralComparable,Array隐式实现:

byte[] rv1 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01 };
byte[] rv2 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05 };

var result = ((IStructuralComparable)rv1).CompareTo(rv2, Comparer<byte>.Default); // returns negative value, because rv1 < rv2
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因你想要使用BitConverter,你必须反转数组,因为BitConverter在大多数架构上都是小端(为了安全 - 你应该检查BitConverter.IsLittleEndian字段并且只有在它返回true时才反向).请注意,这样做效率不高.

var i1 = BitConverter.ToUInt64(rv1.Reverse().ToArray(), 0);
var i2 = BitConverter.ToUInt64(rv2.Reverse().ToArray(), 0);
Run Code Online (Sandbox Code Playgroud)

现在,如果您使用Entity Framework并且需要比较数据库查询中的时间戳,情况会有所不同,因为Entity Framework将检查您的查询表达式,以查找它理解的模式.它不理解IStructuralComparable比较(BitConverter当然也是转换),所以你必须使用技巧.声明字节数组的扩展方法,名称为Compare:

static class ArrayExtensions {
    public static int Compare(this byte[] b1, byte[] b2) {
        // you can as well just throw NotImplementedException here, EF will not call this method directly
        if (b1 == null && b2 == null)
            return 0;
        else if (b1 == null)
            return -1;
        else if (b2 == null)
            return 1;
        return ((IStructuralComparable) b1).CompareTo(b2, Comparer<byte>.Default);
    }
}
Run Code Online (Sandbox Code Playgroud)

并在EF LINQ查询中使用它:

var result = ctx.TestTables.Where(c => c.RowVersion.Compare(rv1) > 0).ToList();
Run Code Online (Sandbox Code Playgroud)

在分析时,EF将看到具有名称Compare和兼容签名的方法,并将其转换为正确的sql查询(从表中选择*,其中RowVersion> @yourVersion)