Curso Entity
Framework - Tratando a Concorrência - XXIV
![]() |
Nesta aula vou apresentar os conceitos sobre a concorrência de dados na utilização do Entity Framework. (aula anterior) |
Chegou o Curso ASP .NET MVC 5 Vídeo Aulas (C#) |
O Entity Framework suporta a concorrência otimista por padrão, e, neste modelo o EF salva a entidade para o banco de dados assumindo que os dados não foram alterados desde que a entidade foi carregada. Se os dados forem alterados será lançada uma exceção e você precisa resolver o conflito antes de tentar salvar novamente.
Vamos ver como tratar a concorrência otimista usando a entidade Aluno do nosso modelo de entidades definido na aula 3 do curso.
Vamos incluir uma coluna com o nome RowVersion do tipo timestamp na tabela Aluno para tratar a concorrência com a entidade Aluno.
Nota: O valor de RowVersion será incrementado automaticamente pelo banco de dados durante a inclusão ou atualização.
RowVersion é um tipo de dados no SQL Server que gera automaticamente números binários únicos sempre que uma operação de atualização ou inclusão for realizada na tabela. Assim o tipo de dados rowversion é apenas um número auto incrementado sendo similar ao tipo de dados timestamp.
Após incluir a coluna tabela vamos atualizar o nosso modelo de entidades. Abra o modelo e clique com o botão direito sobre a entidade Aluno e selecione a opção Update Model From DataBase e a seguir selecione a guia Refresh e clique no botão Finish:
![]() |
![]() |
Após isso você deverá ver a propriedade RowVersion mapeada para a entidade Aluno:
Agora precisamos definir a propriedade Concurrency Mode para Fixed.
Clique na propriedade RowVersion na entidade Aluno e na janela de propriedades altere o valor da propriedade Concurrency Mode de None para Fixed.
Agora o Entity Framework irá incluir a coluna RowVersion na cláusula Where sempre que você realizar uma operação de atualização de dados e se o valor de rowversion for diferente do valor da cláusula where então será lançada a exceção DbUpdateConcurrencyExection.
Vamos fazer um teste usando um cenário onde um Usuario1 e Usuario2 obtendo o mesmo aluno e e atualizando o nome do aluno ao mesmo tempo:
Preparando o ambiente
Vamos usar a solução criada na aula 11 - Entity Framework - Consultas Projeção - EF6_EscolaDB - para testar o cenário da concorrência descrito acima.
Abra a solução EF6_EscolaDB e a seguir clique no menu FILE -> Add -> New Project;
Selecione a linguagem Visual C# e o template Console Application e informe o nome EF6_TestandoConcorrencia :
Para referenciar o EF no projeto incluído, no menu TOOLS clique em Nuget Package Manager -> Manage Nuget Packages for solution;
A seguir clique em Installed packages e depois no botão Manage e marque o projeto que incluímos e a seguir no botão OK.
A seguir inclua uma referência neste projeto ao projeto EF6_EscolaDB e atualize também o arquivo App.Config com a string de conexão para a entidade :
... <connectionStrings> <add name="EscolaDBEntities" connectionString="metadata=res://*/EscolaDB.csdl|res://*/EscolaDB.ssdl|res://*/EscolaDB.msl;provider=System.Data.SqlClient;provider connection string="data source=.\SQLEXPRESS;initial catalog=EscolaDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /></connectionStrings> ... |
Testando a concorrência
A seguir no método Main() do arquivo Program.cs inclua o código abaixo :
using EF6_EscolaDB;
using System.Linq;
namespace EF6_TestandoCorrencia
{
class Program
{
static void Main(string[] args)
{
Aluno Usuario1 = null;
Aluno Usuario2 = null;
//Usuario1 pega o Aluno
using (var context = new EscolaDBEntities())
{
context.Configuration.ProxyCreationEnabled = false;
Usuario1 = context.Alunos.Where(s => s.AlunoId == 1).Single();
}
//Usuario2 pega o mesmo Aluno
using (var context = new EscolaDBEntities())
{
context.Configuration.ProxyCreationEnabled = false;
Usuario2 = context.Alunos.Where(s => s.AlunoId == 1).Single();
}
//Usuario1 atualiza o nome do aluno
Usuario1.AlunoNome = "Editado pelo Usuario1";
//Usuario2 também atualiza o nome do aluno
Usuario2.AlunoNome = "Editado pelo Usuario2";
}
}
}
|
Vamos agora concluir o cenário definindo que o Usuario1 salve as alterações antes do Usuario2.
Dessa forma quando o Usuario2 tentar salvar suas alterações ele vai obter um exceção causada pela concorrência.
Inclua o código destacado em azul abaixo para refletir esse cenário:
using EF6_EscolaDB;
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
namespace EF6_TestandoCorrencia
{
class Program
{
static void Main(string[] args)
{
Aluno Usuario1 = null;
Aluno Usuario2 = null;
//Usuario1 pega o Aluno
using (var context = new EscolaDBEntities())
{
context.Configuration.ProxyCreationEnabled = false;
Usuario1 = context.Alunos.Where(s => s.AlunoId == 1).Single();
}
//Usuario2 pega o mesmo Aluno
using (var context = new EscolaDBEntities())
{
context.Configuration.ProxyCreationEnabled = false;
Usuario2 = context.Alunos.Where(s => s.AlunoId == 1).Single();
}
//Usuario1 atualiza o nome do aluno
Usuario1.AlunoNome = "Editado pelo Usuario1";
//Usuario2 também atualiza o nome do aluno
Usuario2.AlunoNome = "Editado pelo Usuario2";
//--------------------------------------------------------------
//Usuario1 salva as alterações primeiro
using (var context = new EscolaDBEntities())
{
try
{
context.Entry(Usuario1).State = EntityState.Modified;
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("Usuario1 :: Ocorreu uma exceção de concorrência Otimista : " + ex.Message);
}
}
//Usuario2 salva as alterações depois do Usuario1
//Usuario2 vai obter uma exceção de concorrência
//porque CreateOrModifiedDate é diferente no banco de dados
using (var context = new EscolaDBEntities())
{
try
{
context.Entry(Usuario2).State = EntityState.Modified;
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("Usuario2 :: Ocorreu uma exceção de concorrência Otimista : " + ex.Message);
}
}
}
}
}
|
Executando o projeto iremos obter uma exceção exibida no console ocorrida com o Usuario2:
Se você quer saber mais sobre o tratamento da concorrência no EF veja o meu curso na seção de cursos do site:
Entity Framework - O tratamento da concorrência - Curso
Na próxima aula veremos como
usar stored procedures no Entity Framework.
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
|
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências: