rowVersion gets mapped to byte[8] in Entityframe work but when manually casting it's byte[18]

c#-4.0 entity-framework-6 rowversion

Popular Answer

There are three main issues with you. It ought not to be this difficult, yet it is.

The answer I choose is Timestamp.cs. It's a lot simpler. I'll give an illustration at the conclusion.

1. Not comparing like items

rowVersion is an array of 8 bytes. Each byte will be between 0 and 255 and represent a a 64-bit integer's portion.

System.Text.ASCIIEncoding.ASCII.GetBytes instead of numbers, encodes ASCII texts. An array of 18 bytes is returned. Each byte encodes the characters an electronic character and will range from 0 to 9 (48), A to F (65), or x (57). (120).

Solution: You're taking the appropriate steps bylong.Parse("0x0000000000038B8C".Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);

2. Big-endian is used to store timestamps in SQL Server.

BitConverter.ToUInt64 Depending on whether you're using a system where the endianness of the data is big-endian or little-endianulong is little-ending or big-endian. check it out for yourself. is an option. You require a conversion that, regardless of the system you're using, will always be big-endian:

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

3. Unsigned binary comparisons

When comparing in SQL Server0x0FFFFFFFFFFFFFFF < 0xFFFFFFFFFFFFFFFF , 0xFFFFFFFFFFFFFFFF is greater. You must use the same syntax as SQL Server in order to maintain the same meaning.ulong Otherwise, but notlong.0xFFFFFFFFFFFFFFFF becomes -1L instead of what SQL Server perceives it to be,ulong.MaxValue .

Of course, 9 quadrillion things must occur before the high bit of atimestamp even if you might employ the same code to compare two columnsbinary(8) timestamps that were produced in another manner. Duplicating SQL Server's comparison behavior is crucial.

The purest remedy

I use the following answer: Timestamp.cs.

Your code changes to:

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

Basically, after casting toTimestamp , there is no way to err.

Unfortunately, there isn't a decent way to apply this filter on the server-side rather than the client-side regardless of the approach. The topic of this inquiry is that. Guess what I found out! With Entity Framework 6.1.3, zzz-135 zzz! What a cool thing!

HOWEVER, unrelated to your inquiry, you should unquestionably put theId == 2 server-side filtering (before you call ToList). In the alternative, you are sending the complete table to your application and then, on the client side, removing all but one row. What you ought to do is

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
5/23/2017 10:28:54 AM

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow