I have the first EF code model with concurrency tokens on some objects. These markers are defined as byte [] properties and are decorated with [Timestamp] attributes.
[Timestamp] public byte[] ConcurrencyStamp { get; set; }
(I also tried any combination of Timestamp
and ConcurrencyCheck
)
Properties are also marked as concurrency tokens in OnModelCreating
my context:
modelBuilder.Entity<Room>().Property(x => x.ConcurrencyStamp).IsConcurrencyToken();
So here is the scenario:
Some of the objects are serialized as JSON and passed to external clients. When the client updates the object, this changed object is accepted again (like Json), and the changes are applied to the newly received object. In this process, I also update the concurrencytoken value received from the client to the object just obtained from db. Then, when saving changes, the concurrency error does not occur even if the values ββdo not match.
So, to summarize: 1. fetch object from DB 2. serialize object to JSON (including concurrencytoken) 3. client messes with object 4. server receives updated object as json 5. fetch object (by id) from DB 6. apply json values to fetched object (including concurrencytoken) 7. context.savechanges
Checking the log, it seems that EF executes the update statement with the "extracted" concurrencytoken when saving the changes, and not the token set manually from the external object.
UPDATE [dbo].[Rooms] SET [RoomName] = @0, [ConcurrencyStamp] = @1 WHERE (([RoomId] = @2) AND ([ConcurrencyStamp] = @3)) -- @0: 'new room name' (Type = String, Size = -1) -- @1: '1500' (Type = Int64) -- @2: '1' (Type = Int32) -- @3: '1999' (Type = Int64)
(I used longs here, but the same goes for stamp bytes [], which I tried at the beginning).
1999
- the current value of concurrencytoken in the database. 1500
is a token coming from a JSON object that was manually set by setting the property.
Despite the fact that you can see how EF updates the token in the instruction (because I set the property), it still uses the original token value for verification.
Changing properties using the change tracker does not help, the behavior remains unchanged. Any clues? Is this scenario not supported? Am I doing something wrong?
Refresh
Verification works. When creating a new context in a separate thread and performing a change between selections and changes (thus, between steps 5 and step 7) savechanges in step 7 barfs with a ConcurrencyException
.
So, it looks like it works as described, but there is no way to βforceβ the token to be updated externally (which may make sense in some ways, I think).