Inicial > 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.

Deixar mensagem para Eduardo Cancelar resposta