Entity Frameweork 4 - Usando POCO, Code First e as convenções padrão
Esta prevista para o primeiro semestre deste ano uma nova versão do Entity Framework 4 com muitos ajustes com o objetivo de tornar a ferramenta cada vez melhor.
Enquanto a versão final não sai, vamos falar um pouco sobre uma das suas últimas atualizações, a Entity Framework Feature Community Technology Preview - CTP5, mais precisamente da funcionalidade Code-First e POCO.
Obs: Baixe a versão CTP5 aqui : http://tinyurl.com/5rg52tg
Nota: A versão anterior, a CTP4, já permitia usar o recurso do First-Code com um banco de dados existente mas exigia mais intervenção do desenvolvedor com a CTP5 tudo ficou mais simples.
A CTP5 da Entity Framewor 4 inclui atualizações para o recurso Code First e uma interface simplificada da API (DbContext)
O Entity Framework é uma ferramenta OR/M que realiza o mapeamento objeto relacional gerando entidades e mapeando-as para as tabelas do banco de dados.
Na primeira versão do Entity Framework praticamente não havia o que é conhecido como Code-First (Código Primeiro), ou seja, a possibilidade de gerar o modelo de negócios e suas entidades sem ter que primeiro criar o banco de dados.
Para quem trabalha usando o paradigma da orientação a objetos deveria ser natural iniciar o desenvolvimento pelo modelo de entidades, onde as classes são definidas para representar o domínio do negócio. Posteriormente, e a partir destas classes, seria gerado o banco de dados usado pela aplicação para realizar a persistência das informações.
Deveria ser assim, mas a primeira versão do EF não permitia esse recurso.
Tentando contornar este problema eram feitos certos malabarismos, mas ainda assim, havia uma dependência muito forte do mapeamento gerado pelo EF4 através do Entity Data Model, o que incomodava muita gente; até que a Microsoft liberou atualizações que permitem atualmente uma maior independência do Framework através da criação de classes POCO (Plain Old CLR Objects) que não herdam das classes base geradas pelo EF.
Quando decidimos usar o Code-First não precisamos começar nossa aplicação criando o banco de dados ou definindo um esquema mas podemos iniciar escrevendo classes .NET para definir o modelo de objetos do nosso domínio sem ter que misturar a lógica de persistência de dados com as classes.
O Entity Framework por padrão adota algumas convenções (Conventions) que ele usa para realizar algumas operações.
Mas o que vem a ser essas convenções ???
Consultando o dicionário teremos a seguinte definição:
Acordo, pacto, contrato: convenção verbal , aquilo que está geralmente admitido ou tacitamente contratado.
Em nosso contexto, podemos dizer que uma convenção é uma regra padrão pelo qual não teremos que fazer algumas configurações de mapeamento para nossas entidades, sendo que o EF4 vai , baseado nessas convenções, realizar as tarefas de forma automática.
Na CTP5 , as convenções estão definidas por uma hierarquia de subclasses que implementam um contrato comum chamado IConvention. Uma simples definição deste contrato pode ser visto no código abaixo:
public interface IConvention { } |
Public Interface IConvention |
C# | VB .NET |
Debaixo de IConvention
temos elementos como AttributeConfigurationConvention,
IDbConvention e IEdmConvention que nos interessam mais ,
uma vez que eles representam os contratos através dos quais
foram implementadas as diversas convenções.
Neste artigo, antes de entrar em detalhes sobre as Convenções,
eu vou criar um exemplo no EF4 para mostrar como ele se comporta
usando as convenções padrão, para entendermos o seu
comportamento e assim alterá-lo se assim desejarmos.
CTP5 - Usando POCO com as convenções padrão
Se usarmos o EF para realizar o mapeamento criando o Entity Data Model teremos uma grande ajuda da ferramenta mas em muitos casos isso ao invés de ajudar acaba atrapalhando pois o código verboso gerado pode ser um problema para integrar com o nosso modelo ou mesmo transmitir usando Web Services.
Vamos então mostrar como usar POCO sem criar o Entity Data Model e também usar o Code-First gerando o banco de dados e as tabelas a partir de nossas entidades.
Mas
o que são essas classes POCO ? POCO - Plain Old CLR
Object - são classes simples de domínio que possuem
apenas get/sets e um construtor e que não dependem de
nenhum framework; |
Vamos iniciar criando o nosso modelo de negócio através da definição das classes do nosso domínio. Para tornar a tarefa mais suave e de fácil entendimento vou adotar um modelo simplificado que pode ser visto no diagram de classes a seguir:
O nosso
modelo de negócio consiste de duas classes:
O modelo de classes representa um Curso que possui 1 ou mais alunos. Temos aqui uma associação que representa o relacionamento um-para-muitos. O relacionamento
um-para-muitos é usado quando uma entidade A pode se
relacionar com uma |
A cardinalidade é um conceito importante para ajudar a definir o relacionamento, ela define o número de ocorrências em um relacionamento. Para determinar a cardinalidade, deve-se fazer a pergunta relativa ao relacionamento em ambas as direções. No exemplo a seguir, temos
Para implementar o nosso exemplo eu vou usar o Visual Basic 2010 Express Edition e criando um novo projeto chamado EF4_Poco_Escola via menu File->New Project escolhendo o template Windows Forms Application;
Obs: Você vai precisar ter instalado o SQL Server 2005 ou 2008 Express Edition.
No menu Project clique em Add Reference;
Selecione a guia Browse e localize a dll EntityFramework na pasta onde foi instalada a CTP5 (c:\Arquivos Programas)
Os recursos da EF Code First CTP5 tem um nome de assembly atualizado e novo namespace .NET:
No formulário form1.vb vamos definir uma interface bem simples apenas para exibir as mensagens durante a execução do código.
Inclua um controle ListBox (lstResultado) e um botão de comando (btnExecutar) conforme o leiaute da figura abaixo:
Definindo as classes de negócio
Vamos definir as classes Curso e Aluno no projeto da seguinte forma:
1 - No menu Project selecione Add Class e informe o nome Modelo.vb e clique no botão Add;
A seguir defina as classes Curso e Aluno no arquivo Modelo.vb conforme o código abaixo:
Public Class Curso Private m_CursoId As Integer Public Property CursoId() As Integer Get Return m_CursoId End Get Set(ByVal value As Integer) m_CursoId = valu End Set End Property Private m_nome As String Public Property Nome() As String Get Return m_nome End Get Set(ByVal value As String) m_nome = value End Set End Property Private m_escolaid As Integer Public Property EscolaId() As Integer Get Return m_escolaid End Get Set(ByVal value As Integer) m_escolaid = value End Set End Property Public Property Alunos() As ICollection(Of Aluno) Get Return m_Alunos End Get Set(ByVal value As ICollection(Of Aluno)) m_Alunos = value End Set End Property Private m_Alunos As ICollection(Of Aluno) End Class Public Class Aluno Private m_AlunoId As Integer Public Property AlunoId() As Integer Get Return m_AlunoId End Get Set(ByVal value As Integer) m_AlunoId = value End Set End Property Private m_nome As String Public Property Nome() As String Get Return m_nome End Get Set(ByVal value As String) m_nome = value End Set End Property Private m_Email As String Public Property Email() As String Get Return m_Email End Get Set(ByVal value As String) m_Email = value End Set End Property Public Property Curso() As Curso Get Return m_curso End Get Set(ByVal value As Curso) m_curso = value End Set End Property Private m_curso As Curso End Class |
2 - No menu Project selecione Add Class e informe o nome AcessoDados.vb e clique no botão Add;
Vamos definir a classe AcessoDados que herda de DbContext que permite o acesso mais fácil a consultas e trabalhar com os dados das entidades como objetos.
Imports System.Data.Entity Public Class AcessoDados Public Class ContextoCurso Inherits DbContext Private m_Cursos As DbSet(Of Curso) Public Property Cursos() As DbSet(Of Curso) Get Return m_Cursos End Get Set(ByVal value As DbSet(Of Curso)) m_Cursos = value End Set End Property Private m_Alunos As DbSet(Of Aluno) Public Property Alunos() As DbSet(Of Aluno) Get Return m_Alunos End Get Set(ByVal value As DbSet(Of Aluno)) m_Alunos = value End Set End Property End Class End Class |
Um dos aprimoramentos digno
de nota que o CTP5 é uma versão simples das duas
classes : ObjectContext e ObjectSet; - ObjectContext permite consultar, controle de alterações e salvar no banco de dados. - ObjectSet encapsula os conjuntos de objetos semelhantes. O DbContext é um invólucro para ObjectContext e além disso esta classe contém: - Um conjunto de APIs que
são mais fáceis de usar do que a exposta pelo ObjectContext; O DbSet é um invólucro para ObjectSet. |
Definindo o código para executar a criação das tabelas do banco de dados e a persistência dos dados
Vamos agora definir o código no formulário form1.vb no evento Click do botão de comando vamos chamar a rotina geraTabelasBD:
Private
Sub btnExecutar_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btnExecutar.Click geraTabelasBD() End Sub |
O código da rotina geraTabelasBD é visto a seguir:
Private Sub geraTabelaBD() lstResultado.Items.Clear() lstResultado.Items.Add("Gerando as tabelas e o banco de dados") Using contextoCurso As New ContextoCurso() Dim curso As New Curso() With { .Nome = "Entity Framework", .EscolaId = 100 } lstResultado.Items.Add("") lstResultado.Items.Add("Entidade Curso criada com sucesso: nome='Entity Framework', Escolaid=100") contextoCurso.Cursos.Add(curso) lstResultado.Items.Add("") lstResultado.Items.Add("O curso foi incluído na coleção Cursos") Dim macoratti As New Aluno() With { .Nome = "Jose Carlos Macoratti", .Curso = curso, .Email = "macoratti@yahoo.com" } lstResultado.Items.Add("") lstResultado.Items.Add("Entidade Aluno criada com sucesso: nome='Jose Carlos Macoratti'") contextoCurso.Alunos.Add(macoratti) lstResultado.Items.Add("O aluno foi incluído na coleção Alunos") Dim registros As Integer = contextoCurso.SaveChanges() lstResultado.Items.Add("As entidades foram persistidas") lstResultado.Items.Add("") lstResultado.Items.Add("Registros afetados :" + registros.ToString()) End Using End Sub |
Executando o projeto e clicando no botão iremos obter o seguinte resultado:
Feito isso , vamos verificar como o Entity Framework se comportou e quais as operações que ele realizou...
Vamos dar uma olhada no SQL Server instalado na máquina local através do SQL Server Management Studio...
Na figura abaixo vemos que o banco de dados EF4_Poco_Escola.AcessoDados+ContextoCurso foi criado.
Foram criadas também as tabelas Alunos e Cursos e também foram persistidas os dados conforme mostra a figura a seguir:
Obs: O nome das tabelas geradas foram Alunoes e Cursoes. O EF4 aplicou uma convenção baseada na gramática inglesa que cria a tabela com o nome da classe no plural.(*)
O conteúdo as
tabelas Cursos e Alunos exibindo os dados incluídos:
Estrutura das tabelas Cursos e Alunos criadas: |
Partindo das nossas classes POCO o EF4 - CTP5 realizou todo o trabalho de criação do banco de dados e das tabelas e também da persistência das informações.
Resumindo o EF4 fez o seguinte:
Caramba !!! Como ele sabe fazer tudo isso sozinho ????
Elementar meu caro, ele usa as convenções pré-definidas.
E quais seriam então essas convenções ???
Segue um resumo :
Você pode alterar as convenções padrão definindo suas próprias convenções e assim ter um maior controle sobre as tarefas realizadas mas isso é um assunto para outro artigo.
Pegue o projeto completo aqui: EF4_Poco_Escola.zip (versão VB .NET) e EF4_Poco_Conventions.zip (Versão C#)
Eu sei é apenas EF, mas eu gosto...
Referências: