Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>As suggested by Phil, I used optimistic concurrency to ensure the job could not be processed more than once. I realised that rather than having to add a dedicated <code>rowversion</code> column I could use the IsLocked bit column as the <code>ConcurrencyToken</code>. Semantically, if this value has changed since we retrieved the row, the update should fail since only one processor should ever be able to lock it. I used the <a href="http://msdn.microsoft.com/en-us/data/jj591617#1.12" rel="nofollow">fluent API</a> as below to configure this, although I could also have used the <a href="http://msdn.microsoft.com/en-us/data/gg193958.aspx" rel="nofollow">ConcurrencyCheck data annotation</a>.</p> <pre><code>protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity&lt;QueueItem&gt;() .Property(p =&gt; p.IsLocked) .IsConcurrencyToken(); } </code></pre> <p>I was then able to simple the <code>CollectQueueItem</code> method, losing the TransactionScope entirely and catching the more <code>DbUpdateConcurrencyException</code>.</p> <pre><code>public OperationQueueItem CollectQueueItem() { try { var queueItem = this.QueueItems.FirstOrDefault(qi =&gt; !qi.IsLocked); if (queueItem != null) { queueItem.DateCollected = DateTime.UtcNow; queueItem.IsLocked = true; this.SaveChanges(); return queueItem; } } catch (DbUpdateConcurrencyException) //someone else grabbed the job. { } return null; } </code></pre> <p>I reran the tests, you can see it's a great compromise. No duplicates, nearly 100x faster than with <code>REPEATABLE READ</code>, and no <code>DEADLOCKS</code> so the DBAs won't be on my case. Awesome!</p> <pre><code>//Optimistic Concurrency: //Elapsed time: 00:00:00.5065586 //Deadlocked: 624 //Duplicates: 0 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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