Curso Entity 
Framework - Atualizando um grafo de entidade usando o DBContext no modo 
desconectado - XXIII
    
    
    ![]()  | 
    
 Nesta aula vamos mostrar como atualizar um grafo de entidades (um conjunto de entidades ou objetos) no cenário desconectado usando o DBContext. (aula anterior)  | 
  
Chegou o Curso ASP .NET MVC 5 Vídeo Aulas (C#)
Atualizar um grafo de entidades com todas as novas entidades é uma tarefa complexa no cenário desconectado.
O problema na atualização de um grafo de entidades no cenário desconectado é que o contexto não conhece qual operação foi realizada do lado do cliente.
Na figura abaixo temos a representação desse fato onde o contexto não conhece o estado de cada entidade após uma operação ter sido realizada no cliente :

Precisamos identificar o estado de cada entidade no grafo de entidades antes de 
chamar o método SaveChanges().
Existem diferentes padrões para 
identificar o estado de uma entidade que precisamos considerar na concepção da 
camada de dados do Entity Framework.
Padrões para identificar o estado de uma entidade no cenário desconectado
Existem diversas formas de identificar o estado de uma entidade em um cenário desconectado. Dentre elas citamos:
Usar a propriedade Primarykey (Id) de uma entidade
Usando a propriedade state no conjunto de entidades (entity set)
Nota: Você pode usar o seu próprio método para identificar o estado da entidade baseado na sua arquitetura.
1- Usando a propriedade Id (primary Key) de uma entidade
Você pode usar a chave primária - PrimaryKey (Id) de cada entidade para determina o seu estado. Porém, você tem que decidir qual das seguintes regras de arquitetura vai usar:
Cada tipo de entidade deve possuir uma propriedade Id (chave primária)
O valor padrão da propriedade Id deve ser 0
A seguir temos a figura que mostra como usar a propriedade Id para verificar o estado da entidades no cenário desconectado:

No cenário desconectado, o Contexto 2 não conhece o estado de cada entidade. Ele tem que determinar o estado da entidade padrão usando a propriedade PadraoId e o estado do Professor usando a propriedade ProfessorId.
Se os valores de PadraoId e ProfessorId forem iguais a zero, isso significa que elas são uma nova entidade e se o valor não for zero então significa que as entidade foram modificadas.
Na figura temos que Padrao, Professor 1 e Professor 2 possui um valor diferente de zero para a propriedade Id de forma que eles são marcados como Modified e Professor 3 possui o valor zero para o Id e assim ele é marcado como Added.
A seguir veremos o código que representa essa operação.
Atualizando um grafo de entidades aluno usando o Id
Vamos usar a solução criada na aula 22 - Entity Framework - Adicionando um grafo de entidade usando o DBContext no modo desconectado.
Abra a solução e no arquivo Program.cs e inclua o código abaixo neste arquivo:
		 static void Atualizando_GrafoEntidades()
  {
            Padrao PadraoDesconectado = null;
		            using (var contexto = new EscolaDBEntities())
            {
                //
                contexto.Configuration.ProxyCreationEnabled = false;
                //
                PadraoDesconectado = contexto.Padraos.Where(s => s.PadraoId == 58).Include(s => s.Professores).FirstOrDefault<Padrao>();
            }
            // Atualiza a entidade Padrao no modo desconectado
            PadraoDesconectado.PadraoNome = "Nome do Padrão editado e alterado";
		            // Atualiza a coleção Professores editando o primeiro o professor e depois incluindo um novo professor
            PadraoDesconectado.Professores.ElementAt(0).ProfessorNome = "Nome do professor Alterado";
            PadraoDesconectado.Professores.Add(new Professor() { ProfessorNome = "Novo Professor", PadraoId = PadraoDesconectado.PadraoId });
		            using (var novoContexto = new EscolaDBEntities())
            {
                //marca o padrao baseado no PadraoId
                novoContexto.Entry(PadraoDesconectado).State = PadraoDesconectado.PadraoId == 0 ? EntityState.Added : EntityState.Modified;
		                //marca o Professor baseado no PadraodId
                foreach (Professor tchr in PadraoDesconectado.Professores)
                    novoContexto.Entry(tchr).State = tchr.ProfessorId == 0 ? EntityState.Added : EntityState.Modified;
		                novoContexto.SaveChanges();
            }
 }
		 | 
	
Vejamos quais as vantagens dessa abordagem:
E as desvantagens são:
2- Usando a propriedade State em cada entidade
Outra maneira de determinar o estado de uma entidade é ter uma propriedade State em cada tipo de entidade e definir o estado apropriado a partir do lado do cliente no modo desconectado. Dessa forma precisamos definir o estado da entidade como a propriedade State do objeto da entidade e chamar o método SaveChanges no novo Contexto.
						
						Primeiro vamos criar uma 
						interface IEntityObjectState com uma propriedade
						enum chamada EntityObjectState:
 
								        public enum EntityObjectState
        {
            Added,
            Modified,
            Deleted,
            Unchanged
        }
								        interface IEntityObjectState
        {
            EntityObjectState ObjectState { get; set; }
        }
								 | 
							
						
						A seguir vamos implementar a 
						interface IEntityObjectSate em cada entidade. 
						Abaixo vemos um exemplo para as entidades Padrao e 
						Professor :
 
								       public partial class Padrao : IEntityObjectState
        {
            public Padrao()
            {
                this.Alunos = new HashSet<Aluno>();
                this.Professores = new HashSet<Professor>();
            }
								            public int PadraoId { get; set; }
            public string PadraoNome { get; set; }
            public string Descricao { get; set; }
								            public virtual ICollection<Aluno> Alunos { get; set; }
            public virtual ICollection<Professor> Professores { get; set; }
            [NotMapped]
            public EntityObjectState ObjectState
            {
                get;
                set;
            }
        }
								        public partial class Professor : IEntityObjectState
        {
            public Professor()
            {
                this.Cursos = new HashSet<Curso>();
            }
								            public int ProfessorId { get; set; }
            public string ProfessorNome { get; set; }
            public Nullable<int> PadraoId { get; set; }
								            public virtual ICollection<Curso> Cursos { get; set; }
            public virtual Padrao Padrao { get; set; }
								            [NotMapped]
            public EntityObjectState ObjectState
            {
                get;
                set;
            }
        }
								 | 
							
Defina a propriedade State no modo desconectado do lado do cliente e defina o estado da entidade como definido por ObjectState antes de chamar SaveChanges :
								        static void Atualizando_GrafoEntidades_2()
        {
            Professor professorExistente = null;
								            using (var context = new EscolaDBEntities())
            {
                context.Configuration.ProxyCreationEnabled = false;
                professorExistente = context.Professores.FirstOrDefault<Professor>();
            }
								            Padrao PadraoDesconectado = new Padrao() { PadraoNome = "New Standard", ObjectState = EntityObjectState.Added };          
								            professorExistente.ObjectState = EntityObjectState.Modified;
            //adiciona um professor existente  ao Padrao
            PadraoDesconectado.Professores.Add(professorExistente);
            //adiciona um novo Padrao
            PadraoDesconectado.Professores.Add(new Professor() { ProfessorNome = "New teacher", PadraoId = PadraoDesconectado.PadraoId, ObjectState = EntityObjectState.Added });
								            //
            using (var newContext = new EscolaDBEntities())
            {
                // verifica a propriedade ObjectState e marca o apropriedado EntityState 
                if (PadraoDesconectado.ObjectState == EntityObjectState.Added)
                    newContext.Entry(PadraoDesconectado).State = System.Data.Entity.EntityState.Added;
                else if (PadraoDesconectado.ObjectState == EntityObjectState.Modified)
                    newContext.Entry(PadraoDesconectado).State = System.Data.Entity.EntityState.Modified;
                else if (PadraoDesconectado.ObjectState == EntityObjectState.Deleted)
                    newContext.Entry(PadraoDesconectado).State = System.Data.Entity.EntityState.Deleted;
                else
                    newContext.Entry(PadraoDesconectado).State = System.Data.Entity.EntityState.Unchanged;
								                //verifica a propriedade ObjectState de cada professor e marca o apropriedado EntityState 
                foreach (Professor tchr in PadraoDesconectado.Professores)
                {
                    if (tchr.ObjectState == EntityObjectState.Added)
                        newContext.Entry(tchr).State = System.Data.Entity.EntityState.Added;
                    else if (tchr.ObjectState == EntityObjectState.Modified)
                        newContext.Entry(tchr).State = System.Data.Entity.EntityState.Modified;
                    else if (tchr.ObjectState == EntityObjectState.Deleted)
                        newContext.Entry(tchr).State = System.Data.Entity.EntityState.Deleted;
                    else
                        newContext.Entry(tchr).State = System.Data.Entity.EntityState.Unchanged;
                }
                //salva as mudanças
                newContext.SaveChanges();
            }
      }
								 | 
							
As vantagens dessa abordagem são:
Desvantagens:
Apresentando as duas abordagens avalie qual se ajusta melhor ao seu cenário e a utilize quando for preciso.
						
						Na 
						próxima aula veremos a 
						concorrência 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: