'EF code-first can there be multiple entities in DbUpdateConcurrencyException.Entries?
We are using EF 6.x with RefactorThis.GraphDiff; so that a related entity-tree is saved/updated using EF.
We have added RowVersion for each table to capture the concurrency as we are using UoW + Repository pattern with disconnected contexts.
The solution provided at this page has the following code-snippet:
{
var entry = ex.Entries.Single();
}
My question is - is it possible to get more than one entry in the "ex.Entries" ? Will all of them be having Concurrency issue?
Also, additional question - is it possible that RowVersion of "DB" value be smaller than "Original" values?
Solution 1:[1]
No, you still cannot get more then one entry at a time. Unless they fix it, github issue: https://github.com/dotnet/efcore/issues/1002
But you still can catch DbUpdateConcurrencyException as many times as it will be raised, deciding every time how to resolve conflict. Let's get the code sample from here and slightly change it:
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using var context = new PersonContext();
// Fetch a person from database and change phone number
var person1 = context.People.Single(p => p.Id == 1);
person1.PhoneNumber = "555-555-5556";
var person2 = context.People.Single(p => p.Id == 2);
person2.PhoneNumber = "555-555-5557";
// Change the person's name in the database to simulate a concurrency conflict
context.Database.ExecuteSqlRaw(
"UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 1;" +
"UPDATE dbo.People SET FirstName = 'John' WHERE PersonId = 2;");
var saved = false;
while (!saved)
{
try
{
// Attempt to save changes to the database
context.SaveChanges();
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is Person)
{
var proposedValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
foreach (var property in proposedValues.Properties)
{
var proposedValue = proposedValues[property];
var databaseValue = databaseValues[property];
// TODO: decide which value should be written to database
// proposedValues[property] = <value to be saved>;
}
// Refresh original values to bypass next concurrency check
entry.OriginalValues.SetValues(databaseValues);
}
else
{
throw new NotSupportedException(
"Don't know how to handle concurrency conflicts for "
+ entry.Metadata.Name);
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Medbat |