Note that there are some explanatory texts on larger screens.

plurals
  1. POConcurrency check not happening
    text
    copied!<p>I have a code first EF model with concurrency tokens on some of the entities. These tokens are defined as byte[] properties and are decorated with [Timestamp] attributes.</p> <pre><code>[Timestamp] public byte[] ConcurrencyStamp { get; set; } </code></pre> <p>(I've also tried any combination of <code>Timestamp</code> and <code>ConcurrencyCheck</code>)</p> <p>The properties are also marked as concurrency tokens in <code>OnModelCreating</code> of my context:</p> <pre><code>modelBuilder.Entity&lt;Room&gt;().Property(x =&gt; x.ConcurrencyStamp).IsConcurrencyToken(); </code></pre> <p>So, here's the scenario:</p> <p>Some of the entities are serialized as JSON and passed on to external clients. When a client updates an object, that changed object is received again (as Json) and the changes are applied to a freshly fetched object. In this process, I also update the concurrencytoken value received from the client to the object just fetched from the db. Then, when saving changes, no concurrency error is thrown even if the values don't match.</p> <pre><code>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 --&gt; no error if token was changed </code></pre> <p>Checking the log, it seems that EF is doing the update statement with the "fetched" concurrencytoken when saving changes, not the token set manually from the external object.</p> <pre><code>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) </code></pre> <p>(I've used longs here, but the same applies to byte[] stamps, which I tried initially).</p> <p><code>1999</code> is the current concurrencytoken value in the DB. <code>1500</code> is the token coming from the JSON object, which was set manually by setting the property.</p> <p>Even though you can see EF updating the token in the statement (because I set the property) it is still using the original token value to do the check.</p> <p>Changing the properties through the change tracker doesn't help, the behaviour stays the same. Any clues? Is this scenario not supported? Am I doing something wrong?</p> <p><strong>Update</strong> </p> <p>The check <em>does</em> work. When creating a new context in a separate thread and doing a change between the fetch and savechanges (thus between step 5 and step 7), the savechanges in step 7 barfs with a <code>ConcurrencyException</code>. </p> <p>So it appears it works as described, but there's no way to "force" the token to be updated externally (which might make sense in a way, I guess).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload