[英]How to compare two byte arrays with greater than or less than operator value in C# or Linq?
我在Code TimeStamps的Code First Entity Framework中有一個字節數組,映射如下:
[Column(TypeName = "timestamp")]
[MaxLength(8)]
[Timestamp]
public byte[] TimeStamps { get; set; }
上述屬性等於C#中的SQL服務器“timestamp”數據類型。
在SQL服務器中,我可以輕松比較“時間戳”,如下所示......
SELECT * FROM tableName WHERE timestampsColumnName > 0x000000000017C1A2
我希望在C#或Linq Query中實現同樣的功能。 在這里,我編寫了我的Linq查詢,該查詢無法正常工作。
byte[] lastTimeStamp = someByteArrayValue;
lstCostCenter.Where(p => p.TimeStamps > lastTimeStamp);
我也嘗試用BitConverter
來比較一個雙字節數組,這個數組也無效......
lstCostCenter.Where(p => BitConverter.ToInt64(p.TimeStamps, 0) > BitConverter.ToInt64(lastTimeStamp, 0));
如何比較C#或Linq Query中的字節數組。
注意 - 我只是不想比較兩個數組,就像使用SequenceEqual或任何其他方法只是比較並返回true或false。 我希望Linq查詢中的比較大於>或小於<運算符,它提供了正確的數據,如SQL Server查詢。
一種方法是使用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
如果由於某種原因你想使用BitConverter
,你必須反轉數組,因為BitConverter
在大多數架構上都是小端(為了安全起見 - 你應該檢查BitConverter.IsLittleEndian
字段並且只有在它返回true時才反向)。 請注意,這樣做效率不高。
var i1 = BitConverter.ToUInt64(rv1.Reverse().ToArray(), 0);
var i2 = BitConverter.ToUInt64(rv2.Reverse().ToArray(), 0);
現在,如果您使用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);
}
}
並在EF LINQ查詢中使用它:
var result = ctx.TestTables.Where(c => c.RowVersion.Compare(rv1) > 0).ToList();
分析時,EF將看到名稱為Compare
和兼容簽名的方法,並將其轉換為正確的sql查詢(從表中選擇*,其中RowVersion> @yourVersion)
如果您知道兩個字節數組的長度相等且是最重要的字節,則可以使用:
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();
如果我測試以下內容:
byte[] rv1 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01 };
byte[] rv2 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05 };
Console.WriteLine(isGreater(rv1, rv2));
Console.WriteLine(isGreater(rv2, rv1));
...我得到了預期的結果:
False True
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.