Entity Framework - Trabalhando com proxies


 No artigo de hoje vou escrever um pouco sobre como o Entity Framework usa e trabalha com proxies.

   

Ao criar uma instância de um tipo de entidade POCO, o Entity Framework cria uma instância de um tipo derivado gerado dinamicamente, que atua como um proxy para esta entidade.

A entidade POCO tem algumas propriedades virtuais, e este proxy substitui as propriedades virtuais da entidade para executar automaticamente uma ação quando a propriedade for acessada. Este tipo de mecanismo é usado para permitir a o lazy loading o controle de alterações da entidade.(tracking)

Um proxy POCO é uma classe de proxy em tempo de execução (runtime) da entidade POCO. Se você verificar o tipo da entidade em tempo de execução verá que ela tem um nome como: EF_Proxies.Usuario

Geralmente nós não precisamos entender o que são as classes proxy e qual é o uso delas. Mas existem alguns cenários nos quais devemos entender o que são e como atuam essas classes proxies.

- Em alguns cenários, queremos serializar os dados da entidade, e não as classes proxy. Neste caso, podemos prevenir o Entity Framework de a criar uma instância do proxy;
- Em alguns casos, queremos criar uma instância da classe da entidade, e não da classe proxy (que não exigem lazy loading e alteração do tipo de controle de funcionalidade).
- Uma entidade real pode ser obrigada a começar a partir do tipo de proxy. Neste caso, podemos usar o método estático "GetObjectType" de ObjectContext.

Neste artigo veremos como podemos atuar nestes cenários.

Recursos usados:

Criando o projeto no Visual Studio 2013

Então abra o VS 2013 Express for windows desktop clique em New Project;

Selecione a linguagem C# e o template Console Application e informe o nome EF_proxies;

A  seguir vamos incluir um Entity Data Model- EDM no projeto que iremos usar na aplicação exemplo deste artigo.

Clique em PROJECT e a seguir Add New Item;

A seguir selecione a guia Data e o template ADO .NET Entity Data Model e clique no botão Add;

Selecione a opção EF Designer from Database pois vamos gerar um EDM a partir do banco de dados Cadastro.mdf usando como exemplo.

Selecione a conexão com o banco de dados usado para teste, no meu caso o banco de dados Cadastro.mdf, e clique no botão Next>;

A seguir selecione a tabela a partir do qual vamos gerar o EDM. No meu exemplo estou usando a tabela Usuarios;

Encerrando este processo teremos um Entity Data Model com a entidade Usuario mapeada para a tabela Usuarios do banco de dados Cadastro.

Vamos agora mostrar como atuar em cada um dos cenários para tratarmos os proxies gerados pelo Entity Framework.

Desabilitando a criação de Proxies

Em alguns cenários será preciso desativar a criação de uma instância de proxy. Criação do Proxy pode ser desativada usando o sinalizador ProxyCreationEnabled. No exemplo a seguir eu colocá-lo no construtor do contexto.

A Criação Proxy está habilitado por padrão e para desabilitar o recurso basta definir o valor da propriedade ProxyCreationEnable como false.

Nota: Mesmo se a criação de proxy estiver habilitada com esta propriedade, instâncias de proxy somente serão criadas para tipos de entidades que atendam os requisitos para serem proxy.

Para o nosso exemplo temos abaixo o código onde estamos desabilitando a criação de proxies no construtor do contexto:

namespace EF_Proxies
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    
    public partial class CadastroEntities : DbContext
    {
        public CadastroEntities()
            : base("name=CadastroEntities")
        {
            this.Configuration.ProxyCreationEnabled = false;  
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public virtual DbSet<Usuario> Usuarios { get; set; }
    }
}

Podemos também desabilitar a criação de proxy em tempo de criação do objeto do contexto conforme mostra o código a seguir:

using System;
namespace EF_Proxies
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var Context = new CadastroEntities())
            {
                Context.Configuration.ProxyCreationEnabled = false;
                var usu = Context.Usuarios.Find(4);
                if (usu == null)
                {
                    Console.WriteLine("Usuário não encontrado...");
                }
            }
        }
    }
}

Criando uma instância de proxy explicitamente

Quando a propriedade ProxyEnabledCreation for definida como false, uma instância do proxy não será criada se você criar uma instância de uma entidade usando o operador new.

No entanto, podemos criar uma instância do proxy usando o método Create da classe DBSet:

using System;
namespace EF_Proxies
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var Context = new CadastroEntities())
            {
                var  usuario = Context.Usuarios.Create();
            }
        }
    }
}

O método Create possui uma sobrecarga que aceita um tipo genérico e que podemos usar para criar uma instância de um tipo derivado:

using System;
namespace EF_Proxies
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var Context = new CadastroEntities())
            {
                var  usuario = Context.Usuarios.Create<Usuario>;
            }
        }
    }
}

O método Create apenas cria a instância do tipo de entidade, se o tipo de proxy para a entidade não tiver valor. O método Create não adiciona ou anexa a entidade no objeto de contexto.

Obtendo o tipo da entidade a partir do tipo do proxy

Podemos encontrar o tipo da entidade para o tipo de proxy usando o método GetObjectType a partir do ObjectContext.  

using System;
using System.Data.Entity.Core.Objects;
namespace EF_Proxies
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var Context = new CadastroEntities())
            {  
               var entityType = ObjectContext.GetObjectType(usu.GetType()); 
                var usu = Context.Usuarios.Find(4);
                if (usu == null)
                {
                    Console.WriteLine("Usuário não encontrado...");
                }
            }
        }
    }
}

Observe que o tipo passado para GetObjectType é um exemplo de um tipo de entidade que não é um tipo de proxy, em seguida, o tipo de entidade ainda é devolvido.

Isto significa que você sempre pode usar esse método para obter o tipo de entidade real, sem qualquer outra verificação para ver se o tipo é um tipo de proxy ou não. 

Neste artigo apresentamos de forma resumida o que é um proxy no Entity Framework, como podemos habilitar e desabilitar um proxy e como criar uma instância do proxy explicitamente.

E Deus limpará de seus olhos toda a lágrima; e não haverá mais morte, nem pranto, nem clamor, nem dor; porque já as primeiras coisas são passadas.
Apocalipse 21:4

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti