如何在 C# 或 Linq 中比较大于或小于运算符值的两个字节数组? [英] How to compare two byte arrays with greater than or less than operator value in C# or Linq?

查看:27
本文介绍了如何在 C# 或 Linq 中比较大于或小于运算符值的两个字节数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a byte array in my Code First Entity Framework for SQL TimeStamps, mapping as given below:

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

上述属性相当于C#中的SQL servertimestamp"数据类型.

The above property is equal to SQL server "timestamp" Data type in C#.

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

In SQL server I can compare "timestamp" easily as below...

SELECT * FROM tableName WHERE timestampsColumnName > 0x000000000017C1A2

我想在 C# 或 Linq Query 中实现相同的目标.在这里,我编写了我的 Linq 查询,但无法正常工作.

Same thing I want to achieve in C# or Linq Query. Here I have written my Linq query, which is not working properly.

 byte[] lastTimeStamp = someByteArrayValue;
 lstCostCenter.Where(p => p.TimeStamps > lastTimeStamp);

我也试过用 BitConverter 来比较一个同样不工作的两字节数组...

I have also tried with BitConverter to compare a two byte array which is also not working...

 lstCostCenter.Where(p => BitConverter.ToInt64(p.TimeStamps, 0) > BitConverter.ToInt64(lastTimeStamp, 0));

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

How can I compare byte arrays in C# or Linq Query.

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

推荐答案

一种方法是使用 IStructuralComparableArray 隐式实现:

One way is to use IStructuralComparable, which Array implicitly implements:

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

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

If for some reason you want to use BitConverter, you have to reverse arrays, because BitConverter is little endian on most architectures (to be safe - you should check BitConverter.IsLittleEndian field and reverse only if it returns true). Note that it's not very efficient to do this.

var i1 = BitConverter.ToUInt64(rv1.Reverse().ToArray(), 0);
var i2 = BitConverter.ToUInt64(rv2.Reverse().ToArray(), 0);

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

Now if you use Entity Framework and need to compare timestamps in database query, situation is a bit different, because Entity Framework will inspect your query expression looking for patterns it understands. It does not understand IStructuralComparable comparisions (and BitConverter conversions too of course), so you have to use a trick. Declare extension method for byte array with the name 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);
    }
}

并在 EF LINQ 查询中使用它:

And use that in EF LINQ query:

var result = ctx.TestTables.Where(c => c.RowVersion.Compare(rv1) > 0).ToList();

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

When analyzing, EF will see method with name Compare and compatible signature and will translate that into correct sql query (select * from Table where RowVersion > @yourVersion)

这篇关于如何在 C# 或 Linq 中比较大于或小于运算符值的两个字节数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆