O Entity Framework (EF4) faz parte da família de tecnologias do ADO.NET oferecem o mapeamento objeto relacional (OR/M) a um nível conceitual de abstração. O EF4 possui novas funcionalidades e melhorias, as quais foram sugeridas por muitos desenvolvedores desde a versão 1.0. Desta forma, possibilitou "aproximar" de algumas características oferecidas em outras ferramentas de mapeamento objeto relacional, como NHibernate. As ferramentas de mapeamento objeto-relacional são usadas para eliminar grande parte do código tedioso necessário para recuperar e persistir dados de um banco de dados.

Através de uma interface visual, o desenvolvedor usa-a para criar classes que são mapeadas para tabelas, relacionamentos, stored procedures e outros objetos em um banco de dados. Uma das grandes novidades do EF4 é a capacidade de criar um ADO.NET Entity Data Model e então construir a base de dados a partir do modelo. Anteriormente, o desenvolvedor precisava criar o banco de dados e depois gerar o modelo.

Sendo assim, o objetivo deste artigo é mostrar como fazer o mapeamento e CRUD com Entity Framework 4 partindo de um banco de dados em MySQL, já que a maioria dos artigos mostram como fazer o mapeamento com o banco de dados SQL Server. E construir uma simples aplicação utilizando-se das três camadas e a linguagem C#.

Requerimentos

Iniciaremos nosso exemplo criando uma database com o nome de BDEntity, como mostra a Figura 1.

Diagrama de banco de dados
Figura 1. Diagrama de banco de dados

Projeto

Para o nosso projeto será utilizado o modelo de três camadas, como descrito abaixo:

  • BLL - (Business Logic Layer) responsável pela lógica do negócio;
  • DAL - (Data Access Layer) responsável pelo acesso e persistência dos dados - interface e classes de acesso a dados usando o Entity Framework;
  • UI - (User Interface) responsável pela interface com o usuário - Aplicação WEB.

No Visual Studio 2010 selecione File | New | Project. No dropdown selecione o .NET Framework 4, em Installed Templates | Web escolha Empty ASP.NET Web Application. Preencha o campo Name com AppEntity e mantenha a opção “Create directory for solution” selecionada e clique em OK. Conforme traz a Figura 2.

Iniciando projeto
Figura 2. Iniciando projeto

Na Solution Explorer, a camada UI já está adicionada ao projeto, já que escolhemos o template ASP.NET web application.

Então, adicione dois novos projetos do tipo Class Library dentro da solução. Para fazer isso, com o botão direito sobre a Solution Explorer e depois em Add | New Project, será apresentada uma tela como mostra a Figura 3.

Então selecione o template Windows | Class Library.

No campo Name, preencha com os nomes de Entity.Bll e Entity.Dal respectivamente.

Adicionando projetos para a camada de negócios e dados
Figura 3. Adicionando projetos para a camada de negócios e dados

A solução deverá possuir três projetos como mostra a Figura 4.

Solução com três projetos
Figura 4 - Solução com três projetos

A camada de acesso a dados (DAL)

No projeto Entity.DAL será utilizado o Entity Data Model com base em nosso modelo de dados. Clique com o botão direito sobre o projeto Entity.DAL e selecione Add |New Item. A seguir selecione o template Data | ADO .NET Entity Data Model , informe o nome model.edmx e clique no botão Add. A Figura 5 traz a demonstração.

Adicionando Modelo Entity Data Model
Figura 5 - Adicionando Modelo Entity Data Model

A seguir, é mostrado um assistente que permite escolher dentre duas opções, tais como Generate from database e Empty Model. A primeira opção permite criar o mapeamento a partir do banco de dados, e a segunda permite criar um modelo de dados e então criar o script necessário para construir a base de dados. A Figura 6 mostra as duas opções.

Opções para modelo de dados
Figura 6 - Opções para modelo de dados

Então, selecione a opção Generate from database e em seguida pressione Next. Após, selecione a conexão com o banco de dados, como mostra a Figura 7, e clique em Next.

Conexão com banco de dados
Figura 7. Conexão com banco de dados
Nota: Para configurar a conexão com o banco de dados clique em New Connection.

Em seguida selecione as tabelas e aceite o nome do Namespace como testModel, como traz a Figura 8 e clique em Finish.

Adicionando tabelas para o modelo
Figura 8 - Adicionando tabelas para o modelo

Por fim, como mostra a Figura 9, as entidades foram criadas e o mapeamento ORM gerado automaticamente pela ferramenta.

Entidades e mapeamento
Figura 9 - Entidades e mapeamento

Na Figura 9 é possível observar as entidades, tbsecao, tbcategoria e tbproduto criadas, bem como o mapeamento em Mapping Details . O arquivo Model.edmx possui um arquivo associado que foi gerado automaticamente pelo Entity. Abra o arquivo associado ModelDesigner.cs e veja o comentário adicionado, como mostra a Figura 10. Esta mensagem indica que o arquivo foi gerado automaticamente pelo template e modificações manuais podem causar comportamento inesperado, bem como a perda de informações caso o modelo seja gerado novamente pelo Entity Data Model.

Comentário de aviso
Figura 10 - Comentário de aviso

A partir disso, é necessário definir alguns métodos para cada entidade. Para isso, será criada uma Interface. E a seguir, uma classe abstrata que implementa esta interface. E consequentemente, devemos criar as classe concretas das entidades tbsecao, tbcategoria e tbproduto que herdam a classe abstrata.

A criação do mapeamento relacional a partir da existência de uma base de dados, a criação da estrutura para um projeto em três camadas. Sendo assim, a partir do que foi explicado, podemos começar com a criação das Interfaces, Classes e métodos responsáveis pela camada de acesso DAL. Antes de começar com a definição dos métodos, queria mostrar a User Interface que iremos criar ao decorrer dos artigos, pois temos que saber onde iremos chegar com estes tutorias, não é mesmo? A Figura 11 traz a interface administrativa do nosso sistema.

User Interface Administrativa
Figura 11 - User Interface Administrativa

Definição dos métodos no projeto Entity.DAL

A criação de um projeto bem organizado e com comentários facilita em manutenções posteriores. Para tanto vamos começar na criação de folders e Interfaces. Crie um folder com nome de Interfaces e dentro do folder interfaces, crie duas interfaces ICrud.cs e IID.cs que conterá as assinaturas dos métodos.

Nota: Clique com o botão direito sobre o folder interfaces e selecione Add |New Item. A seguir selecione o template Code | Interface e informe o nome ICrud.cs e clique em Add. Faça o mesmo para a interface IID.cs

1- No arquivo ICrud.cs defina do código, como mostrado na Listagem 1.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects.DataClasses;
using System.Linq.Expressions;
 
namespace Entity.DAL.Interfaces
{
    public interface ICrud<T> where T: EntityObject, Interfaces.IID
    {
 
            bool Create(T entity);
            bool Update(T entity);
            bool Delete(int id, T entity);
            T GetByID(int id, T entity);
            IQueryable<T> ALL();
           
    }
} 
Listagem 1. Definição dos métodos CRUD

A interface ICrud é fortemente tipada e está recebendo como parâmetro uma entidade, onde T é do tipo EntityObject , ou seja, pode-se usar como parâmetro qualquer Entidade do modelo criado. Ainda sim, deve-se herdar a interface IID, que será usada pelos métodos. Você deve estar curioso para saber o porquê de herdar a interface IID. A interface IID foi criada com o objeto de trabalhar com a propriedade ID de cada entidade. Por seguinte, podemos definir os principais métodos para a manipulação no banco de dados. 2-) Definição do código no arquivo IID.cs, como mostrado na Listagem 2.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; 

namespace Entity.DAL.Interfaces
{
    public interface IID
    {
        Int32 ID { get; }
    }
} 
Listagem 2. Definição da propriedade ID

Também, no código da Interface foi adicionado dois Namespaces.

3-) A partir disso, será necessário criar uma classe abstrata que irá implementar a Interface ICrud.cs.

Clique com o botão direito sobre o projeto Entity.DAL e selecione Add |New Item. A seguir selecione o template Code | Class e informe o nome Crud.cs e clique em Add.

4-) Definição do código no arquivo Crud.cs, como mostrado na Listagem 3.


namespace Entity.DAL

{

    public abstract class Crud<T> : Interfaces.ICrud<T>
    where T : EntityObject, Interfaces.IID

    {

       //criando uma estancia do contexto definido pelo Entity Data Model 
       //no arquivo Model.Edmx

        private testEntities context = new testEntities();

        public bool Create(T entity)

        {

            try

            {

                context.AddObject(entity.GetType().Name, entity);

                context.SaveChanges();

                return true;

            }

            catch

            {

                return false;

            }

        }

        public bool Update(T entity)

        {

            try

            {

                context.ApplyCurrentValues<T>(entity.GetType().Name, entity);

                return true;

            }

            catch

            {

                return false;

            }

        }

        public IQueryable<T> ALL()

        {

            return context.CreateObjectSet<T>();

        }

        public bool Delete(int id, T entity)

        {

            try

            {

                var _entity = this.GetByID(id,entity);

                context.DeleteObject(_entity);

                context.SaveChanges();

                return true;

            }

            catch

            {

                return false;

                throw;

            }

        }

        public T GetByID(int id, T entity)

        {

            string tablename = entity.GetType().Name;

            return context.CreateQuery<T>(tablename).Where
              (q => q.ID == id).FirstOrDefault();

        }

    }

}
Listagem 3. Implementando métodos de manipulação

No código apresentado na Listagem 3 foi criado uma estância do contexto definido pelo Entity Data Model no arquivo Model.Edmx. Você pode observar o nome na propriedade, como mostra a Figura 12.

Propriedade Entity Container Name
Figura 12 - Propriedade Entity Container Name

A expressão Where(q => q.ID == id) dentro do método GetByID, só é possível porque utilizamos herança.

5-) Criar três classes partial com os nomes de tbsecao, tbcategoria e tbproduto. Estas classes deveram herdar a Interface IID, como mostrado nas Listagens 4, 5 e 6.


namespace Entity.DAL

{

    public partial class tbcategoria : Interfaces.IID

    {

     }
}
Listagem 4. Classe Partial tbcategoria

namespace Entity.DAL

{

    public partial class tbproduto : Interfaces.IID

    {

     }
}
Listagem 5. Classe Partial tbproduto

namespace Entity.DAL

{

    public partial class tbsecao : Interfaces.IID

    {

     }
}

Listagem 6. Classe Partial tbsecao

Estas classes devem ter o mesmo nome das classes partial que estão dentro do arquivo Model.Designer.cs. Poderíamos colocar a herança dentro das classes que estão dentro do Model.Designer, porém caso o modelo seja gerado novamente poderá ocorrer perda de informações. O próximo passo é criar as três classes concretas SecaoData, CategoriaData e ProdutoData, como traz as Listagens 7, 8 e 9.


namespace Entity.DAL

{

    public class SecaoData : Crud<tbsecao>

    {

        //criando uma instancia do contexto definido pelo 
        //Entity Data Model no arquivo Model.Edmx

        private testEntities context = new testEntities();

        public tbsecao GetSecao()

        {

            tbsecao _secao = new tbsecao();

            return _secao;

        }

        public IQueryable<tbsecao> Filter(string _filter)

        {

            IQueryable<tbsecao> _tbsecao = null;

            try

            {

                _tbsecao = context.tbsecao.Where(s => s.TITULO.IndexOf(_filter) > -1);

                return _tbsecao;

            }

            catch { return _tbsecao = null; }  

        }      

     }
}
Listagem 7. Classe concreta SecaoData

namespace Entity.DAL

{

    public class CategoriaData : Crud<tbcategoria>

    {

     }
}
Listagem 8. Classe concreta CategoriaData

namespace Entity.DAL

{

    public class  ProdutoData: Crud<tbproduto>

    {

     }
}
Listagem 9. Classe concreta ProdutoData