Início > Ado.Net > Mapeamento com o Entity FrameWork usando 3 camadas (3° Parte)

Mapeamento com o Entity FrameWork usando 3 camadas (3° Parte)

23 de junho de 2009 Deixe um comentário Go to comments

Olá , hoje iremos continuar nosso projeto com o Entity Framework (veja aqui a  1° Parte e  2° Parte)

No segundo artigo criamos nosso mapeamento no Entity Framework, repare que o processo foi muito simples, nesta  3° parte iremos  criar os métodos Crud de nossas entidades mapeadas.

Para ficar claro que estamos fazendo, crie um novo projeto do tipo Class Library  na sua solução e chame ele BancoHoras.DAL este projeto irá armazenar a classe  Crud.

Neste projeto, exclua a classe Class1.cs criada junto com o projeto e insira uma nova classe chamada AcessoDados.cs

Deixe esta classe conforme o exemplo abaixo:

Inclua as seguintes referências

using System.Data.Objects;

using System.Data.Objects.DataClasses;

using BancoHoras.Interfaces;

using BancoHoras.Entities

 

As referências acima são necessárias para que nosso sistema funcione, o System.Data.Objects e o System.Data.Objects.DataClasses incluem as classes bases do Entity Data Model, para saber mais, consulte os link´s:

http://msdn.microsoft.com/en-us/library/system.data.objects.dataclasses.aspx

http://msdn.microsoft.com/en-us/library/system.data.objects.aspx

A referência BancoHoras.Entities , representam o projeto que contém nosso modelo de entidade e a referência BancoHoras.Interfaces será comentada na 4° parte do artigo, por enquanto apenas inclua a referência.

public class AcessoDados<T> : EntityObject where T : EntityObject, IEntityID

    {

 

        private BancoDeHorasEntities context;

 

        public string NomeEntidade

        {

            get

            {

                T entidade = Activator.CreateInstance<T>();

                return entidade.GetType().Name;

            }

 

        }

 

        /// <summary>

        /// Método para Buscar Entidade por ID.

        /// </summary>

        /// <param name="id">Id da Entidade</param>

        /// <returns>Entidade</returns>

        public T GetById(int id)

        {

            using (context = new BancoDeHorasEntities())

            {

                var entidade = (from e in context.CreateQuery<T>(NomeEntidade)

                                where e.Id == id

                                select e).FirstOrDefault();

                return entidade;

            }

        }

 

        /// <summary>

        /// Método para retornar todos os registros da tabela

        /// </summary>

        /// <returns>Entidade</returns>

        public List<T> GetAll()

        {

            using (context = new BancoDeHorasEntities())

            {

                var entidade = from e in context.CreateQuery<T>(this.NomeEntidade)

                               select e;

                return entidade.ToList();

            }

        }

 

        /// <summary>

        /// Método para inserir uma entidade

        /// </summary>

        /// <param name="entidade"></param>

        public void Criar(T entidade)

        {

            using (context = new BancoDeHorasEntities())

            {

                context.AddObject(NomeEntidade, entidade);

                context.SaveChanges();

            }

        }

 

        /// <summary>

        /// Método para atualizar uma entidade

        /// </summary>

        /// <param name="entidade"></param>

        public void Atualizar(T entidade)

        {

            using (context = new BancoDeHorasEntities())

            {

                var original = (from e in context.CreateQuery<T>(NomeEntidade)

                                       where e.Id == entidade.Id

                                       select e).FirstOrDefault();

                context.ApplyPropertyChanges(original.EntityKey.EntitySetName, entidade);

                context.SaveChanges();

            }

        }

 

        /// <summary>

        /// Método para excluir uma entidade

        /// </summary>

        /// <param name="entidade"></param>

        public void Excluir(int id)

        {

            using (context = new BancoDeHorasEntities())

            {

                var entidade = this.GetById(id);

                context.DeleteObject(entidade);

                context.SaveChanges();

            }

        }

    }

 

A classe acima esta herdando da interface  IEntityID esta interface faz parte do projeto BancoHoras.Intefaces, por isso não iremos nos preocupar com ela neste momento, outra herança que esta nesta classe é a EntityObject.  O trecho  T : EntityObject, IEntityID

esta dizendo que todos os objetos utilizados na instancia da classe deverão implementar o EntityObject e IEntityId, isso é necessário para que possamos criar nossos métodos genéricos.

O BancoHorasEntities é a classe do nosso modelo de entidades criado no EntityFramework, estamos utilizando ele como um campo da classe para que seja utilizado em todos os métodos.

A intenção deste projeto é criar o acesso Crud de forma genérica, ou seja, apenas uma classe que será reutilizada para todas as entidades, por isso iremos criar uma propriedade chamada NomeEntidade, esta propriedade irá receber o objeto genérico e buscar o nome do mesmo para passar para os métodos necessários.

O método GetById recebe o id da entidade e retorna  a entidade preenchida do banco de dados, repare que estamos fazendo uso do Linq e EF para abstrair todo o acesso ao banco.

O método GetAll irá retornar todas os registros do banco do tipo da entidade, sem efetuar nenhum filtro nos mesmo. Já o método Criar, irá inserir no banco de dados um registro, o método Atualizar, irá receber uma entidade (EntityState) e atualizar a mesma no banco de dados, repare que neste método temos uma implementação diferenciada, no próximo tópico iremos falar dele, já o método excluir irá excluir um registro do banco de dados.

Nota: Todas as entidades já foram mapeadas no EF, por isso quando passamos uma Entidade para o BancoHorasEntities e efetuamos alguma operação, o framework já executa a operação na tabela especificada no mapeamento.

 

Na próxima etapa deste artigo iremos finalizar e testar nosso projeto com 3 camadas..

 

Abraço

 

 

Categorias:Ado.Net
  1. Igor
    13 de novembro de 2009 às 3:36

    amigo como voce conseguil acessar as propriedades de uma classe generica em tempo de execucao ?var entidade = (from e in context.CreateQuery<T>(NomeEntidade) where e.Id == id select e).FirstOrDefault();no meu projeto gera erro…??????

  2. Nelson
    15 de novembro de 2009 às 19:32

    Igor, Neste caso eu acesso a propriedade Id pois coloquei uma restrição na herança da minha classe, onde eu digo que qualquer entidade que for passada para a classe (generics) terá que implementar a interface (contrato) IEntityWithId, por isso eu consigo ver a propriedade Id, pois ela esta definida na interface.Veja na declaração da classe:public class AcessoDados<T> : EntityObject where T : EntityObject, IEntityIDQual o erro que você esta tendo ?Abs,

  3. Leonardo Constante
    20 de novembro de 2009 às 14:14

    Nelson,Fiquei com uma duvida relacionada ao seu exemplo. No método que faz a exclusão, tem uma chamada para o metódo GetById, sendo que sendo que nesse momento ja foi dado new na variavel context (essa variavel é nivel de classe). E dentro do metodo GetById novamente é dado new na variavel context e consequentemente Dispose devido ao using. As linhas context.DeleteObject(entidade);context.SaveChanges();irão executar normalmente? Porque nesse momento o context foi Disposed…AbraçoLeonardo Xafranski

  4. Fábio
    17 de março de 2010 às 4:03

    Quando você faz o CreateQuery<T>(Entidade) da erro. Notei que o correto seria colocar o nome do EntitySet. Fiz isso e aí passou.Com isto, eu consigo inserir e consultar, porém na hora de fazer Update ele não funciona. Fiz alguns testes acessando o contexto diretamente pela minha aplicação e ele passa sem dar erro mas não atualiza. Aí percebi que funciona se eu retirar a herança de EntityObject da minha classe.Com você aconteceu algo assim ou está funcionando normalmente?AbraçoFábio

  5. Eduardo
    22 de setembro de 2010 às 19:07

    Nelson,A mesma dúvida do Leonardo Constante ocorreu no meu caso.Além disso, quando executamos o código, após efetuar o context.DeleteObject(entidade), então temos o SaveChanges() e, neste momento ocorre o seguite erro:ObjectDisposedException was unhandledThe ObjectContext instance has been disposed and can no longer be used for operations that require a connection.Será que, pelo fato de dentro do GetById termos novamente um novo contexto, não perdemos a referência?

  6. Nelson
    22 de setembro de 2010 às 19:15

    Eduardo, tudo bem.Não iria dar o erro pois os objetos são de instancias diferentes, o que pode estar ocorrendo é um bug que existe na versão 3.5, qual versão vc esta utilizando ?Abs,

  7. Eduardo
    22 de setembro de 2010 às 21:38

    Opa!Tudo bem nelson?A versão que estou utilizando é 4.0.

  8. Eduardo
    22 de setembro de 2010 às 21:43

    Além disso, surgiram 2 duvidas:1. Se eu não quero trabalhar com o interface para os Id, é possível trabalhar da mesma forma para outras camadas, apenas retirando a referência ou tenho que sair ajustando as camadas de negócio e dados?2. Estava efetuando uns testes, como o GetById mas por Nome (como um like) porém… quando tento fazer o where, só me vem o Id para filtro, teria também que padronizar os nomes na interface?

  9. Eduardo
    22 de setembro de 2010 às 21:51

    O GetByName é um método que pretendo fazer com que seja filtrado uma determinada propriedade que não é padronizada, pois tenho por exemplo produtonome e categorianome. Portanto, não acho correto definir na Interface um campo Name, pois cada entidade tem campos diferentes. O que você indica fazer?

  10. Eduardo
    22 de setembro de 2010 às 21:58

    Estava aqui pensando… acredito que, seria talvez válido implementar uma classe para Produto e/ou Categoria que teria métodos específicos de busca. Você acha que é uma solução boa ou existe algo mais correto de se fazer?

  11. Nelson
    23 de setembro de 2010 às 14:12

    Opa, respostas em Ordem:R: Sim, basta criar o campo na interface e um método que utilize este campo para pesquisar, pode ser ate pesquisas linq.R: Eu recomendo você verificar uma Dependency Property e resolver a referencia dinamicamente usando reflection: Veja: http://msdn.microsoft.com/pt-br/library/system.windows.dependencyproperty.aspx

  12. Nelson
    23 de setembro de 2010 às 14:13

    R: Neste caso depende muito do cenário, criar classes especializadas não existe nenhum mal, no entanto o Generics com o Reflection pode te auxiliar muito criar classes genericas que servirão para todos os cenários.R: Depende muito, se tiver familiariade com o Generics e Reflection, derepente pode pensar em construir de forma generica a classe (sirva para todos), mas não vejo nenhum mal tambem criar classes especializadas para estes cenários. Depende muito da aplicação.

  1. No trackbacks yet.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: