I am using Entity Framework on Azure. After makes a few changes to my data I call the DbContext.SaveChanges
.
In my code, Messages
belong to Conversations
. On receiving a message I add it to the Messages table and create its parent in the Conversations table. If I get two messages come in at once with the same parent, there is a possibility of double inserting values with the same primary key into the Conversations table.
The process:
I'll call some "insert conversation if it doesn't exist code":
if (this.Context.Conversations.SingleOrDefault(fc => fc.ConversationId == conversation.ConversationId) == null)
{
Context.Entry(conversation).State = EntityState.Added; //public DbEntityEntry Entry(object entity);
}
Later on I'll call this.Context.SaveChanges
I've been reading SQL Azure and Entity Framework Connection Fault Handling and I'm pretty sure I want to implement a Retry Policy With Transaction Scope.
How do I go about wrapping SaveChanges
in a retry policy
Some thoughts: How do I go about wrapping SaveChanges
in a retry policy. Will this retry the code I ran earlier that checked if the conversation existed? How do I make my retry policy retry for non-transient faults (like PK violations)?
If a retry policy isn't possible , what is the entity framework approach to burying the "create or edit if exists" logic as far down as possible when saving a context? Is it best to just call a stored procedure in this special case?
It sounds more like a concurrency retry pattern that you want:
using (var context = new BloggingContext())
{
var blog = context.Blogs.Find(1);
blog.Name = "The New ADO.NET Blog";
bool saveFailed;
do
{
saveFailed = false;
try
{
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
// Update the values of the entity that
//failed to save from the store
ex.Entries.Single().Reload();
}
} while (saveFailed);
}
Reference:
http://msdn.microsoft.com/en-gb/data/jj592904.aspx
Sadly - you do not. That is not within the scope of what EF can do out of the box. The retry logic explicitly only handles transient connection issues. And there is no retry logic that magically fixes PK issues. There also is no "upsert" (update or insert) logic at all in EF.
You are on your own here - no sense to even ask the devs as they are busy with EF 7 and even drop features temporarily to make that happen (like inheritance). Maybe in a year or two, once EF has more functionality and is stable in v7... but no, nothing there at the moment.
You will have to sort that out in your own application logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With