Skip to content Skip to sidebar Skip to footer

How To Compare Two Byte Arrays With Greater Than Or Less Than Operator Value In C# Or Linq?

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[] Time

Solution 1:

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

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

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

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);

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:

staticclassArrayExtensions {
    publicstaticintCompare(thisbyte[] b1, byte[] b2) {
        // you can as well just throw NotImplementedException here, EF will not call this method directlyif (b1 == null && b2 == null)
            return0;
        elseif (b1 == null)
            return-1;
        elseif (b2 == null)
            return1;
        return ((IStructuralComparable) b1).CompareTo(b2, Comparer<byte>.Default);
    }
}

And use that in EF LINQ query:

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

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)

Solution 2:

If you know that the two byte arrays are equal length and are most significant byte first then this works:

Func<byte[], byte[], bool> isGreater =
    (xs, ys) =>
        xs
            .Zip(ys, (x, y) =>new { x, y })
            .Where(z => z.x != z.y)
            .Take(1)
            .Where(z => z.x > z.y)
            .Any();

If I test with the following:

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

Console.WriteLine(isGreater(rv1, rv2));
Console.WriteLine(isGreater(rv2, rv1));

...I get the expected result of:

False
True

Post a Comment for "How To Compare Two Byte Arrays With Greater Than Or Less Than Operator Value In C# Or Linq?"