gpt4 book ai didi

c#-4.0 - rowVersion 在 Entityframe 工作中被映射到 byte[8],但是当手动转换它时是 byte[18]

转载 作者:行者123 更新时间:2023-12-04 13:48:28 24 4
gpt4 key购买 nike

我正在从数据库中获取 rowVersion 作为 byte[8]

var rowVersion= new MyContext().Employee.FirstOrDefault(x => x.Id).rowVersion;
// suppose above the actual databse values is 0x0000000000038B8C
var rowVersionToLong = BitConverter.ToInt64(rowVersion,0);

现在,如果我手动执行此操作:

String rowversionStr = "0x0000000000038B8C";
byte[] mybyteArray = System.Text.ASCIIEncoding.ASCII.GetBytes(rowversionStr);

这给了我 byte[18],当我将它转换为 Int64 时,它给了我不同的值。

我没听懂。

我想将 rowVersion 作为参数传递给 WebApi get 方法。由于 Byte[] 是不允许的,所以我将它作为字符串传递

更新:

 public IHttpActionResult Get(string rowVersion, int id)
{

var exisitingRowVersion = long.Parse(rowVersion.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);

var result = new MyContext().employees.ToList().Where(x => x.Id == 2 && BitConverter.ToInt64(x.RowVersion, 0) > exisitingRowVersion);

return Ok(result);

不明白为什么这个不起作用。我们基本上是长与长的比较

最佳答案

你有三个主要问题。它不应该这么复杂,但确实如此。

这是我使用的解决方案:Timestamp.cs .这要容易得多。我会在最后举一个例子。

1。不比较苹果与苹果

rowVersion是一个 8 字节的数组。每个字节代表 64 位整数的一部分,并且是 0 - 255。

System.Text.ASCIIEncoding.ASCII.GetBytes编码 ASCII 字符串,而不是整数。它返回一个 18 字节的数组。每个字节代表一个文本字符,将是'0' (48) - '9' (57)、'A' (65) - 'F' (70) 或 'x' (120 ).

解决方案:您在 long.Parse("0x0000000000038B8C".Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); 的正确轨道上

2。 SQL Server 时间戳以大端方式存储

BitConverter.ToUInt64是大端还是小端,取决于您是否在 ulong 所在的系统上运行是大端还是小端。你可以see this for yourself .无论您在何种系统上运行,您都需要始终为大端字节序的转换:

static ulong BigEndianToUInt64(byte[] bigEndianBinary)
{
return ((ulong)bigEndianBinary[0] << 56) |
((ulong)bigEndianBinary[1] << 48) |
((ulong)bigEndianBinary[2] << 40) |
((ulong)bigEndianBinary[3] << 32) |
((ulong)bigEndianBinary[4] << 24) |
((ulong)bigEndianBinary[5] << 16) |
((ulong)bigEndianBinary[6] << 8) |
bigEndianBinary[7];
}

3。二进制比较是无符号的

当 SQL Server 比较 0x0FFFFFFFFFFFFFFF < 0xFFFFFFFFFFFFFFFF 时, 0xFFFFFFFFFFFFFFFF更大。为了保持 SQL Server 对待它的相同含义,您必须使用 ulong 而不是long 。否则0xFFFFFFFFFFFFFFFF变成 -1L而不是 SQL Server 认为的 ulong.MaxValue .

诚然,在 timestamp 的高位之前必须发生 9 千万亿次事情列被使用,但您可以使用相同的代码来比较两个 binary(8)以其他方式生成的时间戳。重要的是复制 SQL Server 的比较行为。

最干净的解决方案

这是我使用的解决方案:Timestamp.cs .

您的代码变为:

var existingRowVersion = (Timestamp)ulong.Parse(rowVersion.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);

var result = new MyContext().employees.ToList().Where(x => x.Id == 2 && (Timestamp)x.RowVersion > exisitingRowVersion);

基本上一旦你转换到Timestamp ,你不会出错的。

遗憾的是,无论您使用哪种方法,都没有很好的方法在服务器端而不是客户端应用此过滤器。这就是 this question 的主题. 猜猜我发现了什么! A way to do this使用 Entity Framework 6.1.3!这有多酷?

但是,这与您的问题无关,您绝对应该将 Id == 2在服务器端过滤(在调用 ToList 之前)。否则,您会将整个表格传输到您的应用程序,然后在客户端丢弃除一行以外的所有内容。你应该这样做:

var existingRowVersion = (Timestamp)ulong.Parse(rowVersion.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);

var result = new MyContext().employees.Where(x => x.Id == 2).ToList().Where((Timestamp)x.RowVersion > exisitingRowVersion);

最佳:

var existingRowVersion = (Timestamp)ulong.Parse(rowVersion.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);

var employee = new MyContext().employees.SingleOrDefault(x => x.Id == 2);
if (employee == null) ... // Deleted
else if ((Timestamp)employee.RowVersion > exisitingRowVersion) ... // Updated

关于c#-4.0 - rowVersion 在 Entityframe 工作中被映射到 byte[8],但是当手动转换它时是 byte[18],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31163205/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com