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: