Entity Framework - Simultaneidade
Qualquer desenvolvedor de acesso a dados enfrenta dificuldade ao responder à pergunta sobre a simultaneidade de dados, “O que acontece se mais de uma pessoa estiver editando os mesmos dados ao mesmo tempo?”
Os mais afortunados entre nós lidam com regras de negócios que dizem "sem problemas, o último em vitórias".
Nesse caso, a simultaneidade não é um problema. Mais provavelmente, não é tão simples assim e não existe solução mágica para resolver todos os cenários de uma vez.
Por padrão, o Entity Framework seguirá o caminho de “último em vitórias”, o que significa que a atualização mais recente é aplicada mesmo se outra pessoa atualizou os dados entre a hora em que os dados foram recuperados e a hora em que os dados foram salvos.
Vamos dar um exemplo para entender melhor. O exemplo a seguir adiciona uma nova coluna VersionNo na tabela Course.
Vá para o designer e clique com o botão direito na janela do designer e selecione atualizar o modelo do banco de dados ...
Você verá que outra coluna foi adicionada na Entidade do curso.
Clique com o botão direito do mouse na coluna recém-criada VersionNo, selecione Propriedades e altere ConcurrencyMode para Fixed, conforme mostrado na imagem a seguir.
Com o ConcurrencyMode de Course.VersionNo definido como Fixo, sempre que um Curso for atualizado, o comando Atualizar procurará o Curso usando seu EntityKey e sua propriedade VersionNo.
Vamos dar uma olhada em um cenário simples. Dois usuários recuperam o mesmo curso ao mesmo tempo e o usuário 1 altera o título desse curso para Matemática e salva as alterações antes do usuário 2. Mais tarde, quando o usuário 2 altera o título daquele curso que foi recuperado antes do usuário 1 salvar suas alterações, naquele caso o usuário 2 obterá exceção de simultaneidade"User2: Optimistic Concurrency exception occured".
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
namespace DatabaseFirstDemo {
class Program {
static void Main(string[] args) {
Course c1 = null;
Course c2 = null;
//User 1 gets Course
using (var context = new UniContextEntities()) {
context.Configuration.ProxyCreationEnabled = false;
c1 = context.Courses.Where(s ⇒ s.CourseID == 1).Single();
}
//User 2 also get the same Course
using (var context = new UniContextEntities()) {
context.Configuration.ProxyCreationEnabled = false;
c2 = context.Courses.Where(s ⇒ s.CourseID == 1).Single();
}
//User 1 updates Course Title
c1.Title = "Edited from user1";
//User 2 updates Course Title
c2.Title = "Edited from user2";
//User 1 saves changes first
using (var context = new UniContextEntities()) {
try {
context.Entry(c1).State = EntityState.Modified;
context.SaveChanges();
} catch (DbUpdateConcurrencyException ex) {
Console.WriteLine("User1: Optimistic Concurrency exception occurred");
}
}
//User 2 saves changes after User 1.
//User 2 will get concurrency exection
//because CreateOrModifiedDate is different in the database
using (var context = new UniContextEntities()) {
try {
context.Entry(c2).State = EntityState.Modified;
context.SaveChanges();
} catch (DbUpdateConcurrencyException ex) {
Console.WriteLine("User2: Optimistic Concurrency exception occurred");
}
}
}
}
}