Concurrency verification does not occur

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 --> no error if token was changed 

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

+4
source share
2 answers

You really can force it. You just need to set the timestamp as follows:

  customerRequest.RowVersion = detachedRequest.RowVersion; Context.Entry(customerRequest).Property(p => p.RowVersion).OriginalValue = customerRequest.RowVersion; Context.Entry(customerRequest).Property(p => p.RowVersion).IsModified = false; 

After that, ef will think that it has not been updated and will throw a concurrency exception when updating.

first tested on ef 6.

+3
source

EF always uses the OriginalValue timestamp selected in step 5 in its UPDATE in step 7.

Setting entity.ConcurrencyStamp = viewModel.ConcurrencyStamp in step 6 only updates CurrentValue .

To install OriginalValue , do this in step 6:

 dbContext.Entry(entity).Property(e => e.ConcurrencyStamp).OriginalValue = viewModel.ConcurrencyStamp; 
+2
source

Source: https://habr.com/ru/post/1502006/


All Articles