Back-End

9 out, 2015

Curso Entity Framework – O ciclo de vida das entidades

Publicidade

Nesta aula vamos tratar do ciclo de vida das entidades no Entity Framework (veja aqui a aula anterior).

Antes de começar a trabalhar com o Entity Framework para realizar operações de inclusão, exclusão e alteração (CRUD), é importante que você compreenda como o Entity Framework gerencia o ciclo de vida das entidades.

Durante o tempo de vida de uma entidade, cada entidade possui um estado baseado na operação que foi realizada sobre a entidade via contexto (DBContext).

O estado da entidade é uma enumeração do tipo System.Data.EntityState que declara os seguintes valores:

  1. Added – A entidade é marcada como adicionada;
  2. Deleted – A entidade é marcada como deletada;
  3. Modified – A entidade foi modificada;
  4. Unchanged – A entidade não foi modificada;
  5. Detached – A entidade não esta sendo tratada no contexto.  

O contexto não só trata a referência para todos os objetos recuperados do banco de dados, mas também detém os estados da entidade e mantém as modificações feitas nas propriedades da entidade. Este recurso é conhecido como controle de alterações ou Change Tracking.

A mudança no estado da entidade de Unchanged para o estado Modified é o único estado que é feito automaticamente pelo contexto.

Todas as outras alterações devem ser feitas explicitamente utilizando métodos adequados de DbContext e DbSet – vamos entrar em detalhes sobre isso mais adiante no curso.

Compreendendo o estado de um entidade

Quando usamos o Entity Framework para criar o modelo de entidades, temos que o contexto trata uma referência para com todos os objetos retornados do banco de dados.

Neste cenário, o contexto trata o estado de uma entidade e mantém as modificações feitas para as propriedades da entidade. Este recurso é conhecido como object tracking ou change tracking. Se você criar uma entidade fora do contexto, o seu estado inicial é Detached, pois o contexto não pode tratar esta entidade.

Nota: De maneira mais precisa, uma entidade fora do contexto não possui estado.

A atribuição Detached é usada na versão 1.0 do Entity Framework – este era o estado quando a entidade não era tratada pelo contexto. Se você anexar uma entidade ao contexto, ela terá o seu estado alterado para Unchaged. Se você retornar uma entidade do banco de dados e, então, liberar a entidade do contexto o estado da entidade será Detached. Se você retornar uma entidade, liberá-la do contexto e criar um novo contexto e adicionar a entidade a ele, a entidade terá o estado Added.

O estado é o relacionamento entre a entidade e o contexto que trata uma referência para a entidade. Você poderia pensar que o estado da entidade reflete o estado da entidade comparado com linha correspondente do banco de dados, mas este conceito esta incorreto.

O contexto representa a aplicação de banco de dados e é por isso que as entidades relacionam seu estado com o contexto e não como banco de dados.

Suponha que você tenha dois métodos em um web service:

  1. Retorna dados do cliente;
  2. Atualiza os dados.

O cliente usa o primeiro método para retornar dados e exibi-los no formulário. Neste método, você cria um contexto que retorna os dados e então destrói o contexto. Após isto, o cliente modifica alguns dados e, então, os salva invocando o segundo método e passando os dados atualizados. No segundo método você cria um novo contexto e anexa a entidade.

O novo contexto não conhece que os dados foram modificados pelo usuário a menos que ele vá ao banco de dados e faça uma comparação dos dados recebidos com os dados gravados. Como fazer uma consulta ao banco de dados consome recursos, isto não é feito de forma automática – o que significa que quando a entidade é anexada ao contexto, ela recebe o estado Unchaged, pois o contexto não sabe nada sobre alterações feitas na entidade. Se a entidade refletisse o seu estado atual em comparação com o banco de dados e não com o contexto seu estado seria Modified, mas não é este o caso.

Dessa forma, tenha em mente que o estado de uma entidade reflete o seu relacionamento com o contexto e não com o banco de dados.

Como o estado de uma entidade afeta o banco de dados

O estado representa não somente o estado da entidade no contexto, mas também como os dados serão persistidos no banco de dados.

Para cada estado existe um comando SQL correspondente.

  • Uma entidade no estado Added é persistida usando o comando INSERT para criar uma nova linha na tabela mapeada;

 

  • Uma entidade que já foi modificada e está no estado Modified será persistida usando o comando UPDATE;

 

  • Uma entidade no estado Deleted utiliza um comando DELETE.

Os estados Detached e Unchaged não possuem impacto no banco de dados, pois uma entidade Detached não está sendo tratada pelo contexto e não pode ser persistida ao passo que uma entidade no estado Unchaged não possui alterações a serem persistidas.

Durante seu tempo de vida, uma entidade pode sofrer alterações no seu estado. Vejamos como isso ocorre e qual API podemos usar para fazer isso de forma manual.

Mudanças de estado no ciclo de vida de uma entidade

O estado de uma entidade é, algumas vezes, definido automaticamente pelo contexto e também pode ser modificado manualmente pelo desenvolvedor.

Embora todas as combinações de alterações de estado sejam possíveis, algumas não terão sentido, por exemplo alterar o estado de Added para Deleted ou vice-versa.

A figura a seguir mostra todos os estados e como as entidades podem passar de um estado para outro:

ef4_cve11

Os diferentes estados das entidades e os métodos do contexto que podem alterar o estado de uma entidade.

Vejamos então os detalhes envolvidos em cada mudança de estado.

Estado Detached

Quando uma entidade está Detached, ela não está vinculada ao contexto e o seu estado não está sendo monitorado.

Ela pode ser liberada, modificada, usada em combinação com outras classe, ou usada da forma que você precisar; como não existe um contexto vinculado a ela, ela não tem significado para o Entity Framework.

Como consequência, o estado Detached é o estado padrão para uma entidade criada (usando o construtor new) porque o contexto não pode monitorar a criação de qualquer objeto no seu código. Isto é verdade mesmo se você instanciar a entidade dentro de um bloco Using do contexto. O estado Detached também é o estado das entidades retornadas do banco de dados quando o monitoramento estiver desabilitado.

Estado Unchanged

Quando uma entidade está no estado Unchaged, ela está vinculada ao contexto mas não foi modificada. Por padrão, uma entidade retornada do banco de dados está neste estado.

Quando uma entidade está anexada ao contexto, ela também está no estado Unchanged. Como o contexto não pode monitorar alterações em objetos que ele não referencia, quando um objeto está anexado, ele assume que ele está no estado Unchanged.

Estado Added

Quando uma entidade está no estado Added, você pode somente alterar o seu estado para Detached.

Mesmo que você faça qualquer alteração na entidade, o seu estado continua como Added, pois alterar o estado para Modified, Unchanged ou Deleted não faria sentido, visto que uma nova entidade não possui correspondência com nenhuma linha do banco de dados.

Estado Modified

Quando uma entidade está no estado Modified significa que ela estava no estado Unchanged e sofreu alguma alteração.

Depois que uma entidade entra no estado Modified, ela pode ter o seu estado alterado para Detached ou Deleted, mas após isso não pode ter o seu estado retornado para Unchanged mesmo que você restaure manualmente os valores originais (a menos que você altere o estado para Detached e em seguida anexe a entidade ao contexto).

Você não pode alterar o estado de Modified para Added (a menos que você altere o estado para Detached e inclua a entidade ao contexto) pois uma linha com o ID da entidade já existe no banco de dados e se fizer isso irá obter um erro em tempo de execução quando for persistir a entidade.

Estado Deleted

Uma entidade entra no estado Delete porque ela estava no estado Unchanged ou Modified e então o método para deletar a entidade foi utilizado.

Este é o estado mais restritivo, pois é inútil mudar este estado para qualquer outro a não ser para Detached.

Na próxima aula vamos tratar dos relacionamentos entre as entidades no Entity Framework.