Introdução ao Entity Framework

Publicado: 28 28UTC setembro 28UTC 2011 em Entity Framework, Linq, Microsoft, Programação, Silverlight

O Entity Framework não é novo, ele já existia no .NET 3.5, como uma nova forma de acesso a dados, nos trazendo a possibilidade de trabalhar com objetos, ao invés de adapters.

Ele nos permite criar aplicações em que o acesso a dados é feito com base em um modelo conceitual e não utilizando comandos diretos à base de dados. Isto permite que o programador se abstraia totalmente da base de dados (criação de ligações de acesso, comandos, parâmetros, etc. ) e utilize apenas objetos durante o desenvolvimento.

A versão 4.0 do Entity Framework, que está disponível na .NET Framework 4.0, tem um conjunto de novas funcionalidades e melhorias, como é o caso de suporte a POCO – Plain Old CLR Objects (permite criar classes que não herdam, nem implementam nenhuma outra classes ou interface), abordagem Model-First (permite criar primeiro o modelo conceptual e, com base nele, criar a base de dados), suporte para o uso de funções em LINQ to Entities, Complex Types (criação de tipos de dados complexos), Deferred Loading ou Lazy Loading (capacidade de carregar as propriedades de associação das entidades no momento em são chamadas, se forem chamadas), etc. Não é especifica apenas para o SQL Server, pois existem providers que permitem usar outras bases de dados, como Oracle, MySql, PostgreSQL, DB2, SQL Anywhere, Ingres, Progress, Firebird, Synergy, etc.

Existem várias vantagens na utilização de um ORM (Object-Relational Mapping), que tornam a sua adopção quase inevitável, mas vejamos o seguinte exemplo:

"SELECT * FROM clientes WHERE nome = ‘Daniel’ AND morada = ‘Casa’"

Este exemplo irá listar todos os clientes que tenham como nome “Daniel” e que tenham como morada a “Casa”.

Imaginemos que o programador ou o DBA (administrador do banco de dados) altera o campo “nome” para “nomecompleto”, pois quer que se registe o nome completo do utilizador e, desta forma, o nome do campo fica mais coerente. Se aplicação for compilada não é detectado qualquer problema e só no momento de execução irá ocorrer um erro. Situações como estas são muito frequentes e podem representam vários erros na aplicação.

Este é apenas um exemplo de como se pode beneficiar, e muito, da utilização do Entity Framework, mas existem muito mais vantagens com a utilização de LINQ to Entities, intellisense, código mais fácil de manter e atualizar.

Neste artigo, que será uma breve introdução ao Entity Framework, irei apenas mostrar como construir um modelo relacional de uma base de dados SQL, uma abordagem database-first, e como executar algumas operações CRUD.

Para melhor demonstrar o Entity Framework, prefiro ir explicando os conceitos conforme desenvolvemos um exemplo, de forma a termos uma visão real do que a plataforma faz.

Criação do Modelo Relacional (database-first)

Para criação de um modelo relacional iremos usar a seguinte base de dados SQL:

modelo_relacional

Figura 1 – Modelo Relacional

Como é possível ver nesta imagem, existem apenas três tabelas, com as respectivas chaves primárias/estrangeiras: Person, PersonPhones e PersonEmails.

Criação do Projeto

Vamos criar um novo projeto no Visual Studio. File => New => New Project, escolha Silverlight Application, eu nomeei o mesmo como ExemploCRUD. Ver figura 2 e 3.

newProject

Figura 2 – Novo Projeto

newProject_WebProject

Figura 3 – Definições do Projeto Silverlight

Criação do ADO.NET Entity Data Model

O próximo passo é adicionar um novo item ao projeto ExemploCRUD.Web. Menu => Project => “Add New Item”, selecione no grupo de templates “Data” o item “ADO.NET Entity Data Model”. Isso irá iniciar um Wizard que permitirá criar o modelo.

Eu nomeei como ExemploModel.edmx, conforme figura 4.

exemploModel

Figura 4 – Add New Item

Logo em seguida selecione “Generate from database” e click em “Next”.

A próxima opção permite fazer a conexão com o banco de dados, você pode escolher uma já existente ou criar uma nova conexão.

No meu caso, eu criei uma nova conexão, basta clica no botão “New Connection…”. Abrirá a janela de Connection Properties, informe os dados sobre o banco e click em OK. Ver Figura 5.

new_connection

Figura 5 – Connection Properties

De volta à janela “Entity Data Model Wizard”, marque as opções conforme a Figura 6 e para o nome da conexão, nomeio ExemploEntities.

exemploEntities

Figura 6 – ExemploEntities

Feito isso click em Next. A última opção deste Wizard é onde são selecionados os objetos a serem utilizados no modelo. Neste exemplo são escolhidas as três tabelas supracitadas. Ver figura 7.

exemploModelTables

Figura 7 – Finalização

  • Pluralize or singularize generated object names: Deixar no plural os nomes dos objetos, por exemplo Order passar para Orders. Vamos marca-la;
  • Include foreign keu columns in the model: Devemos deixar marcada para expor as chaves estrangeiras do nosso modelo de banco de dados;
  • Model Namespace: o Namespace no qual vai estar contido o modelo, eu nomeei ExemploModel.

Click em Finish, após este processo está criado o arquivo edmx, que não é mais do que um conjunto de classes e métodos que nos permitirá acessar o banco de dados de uma forma simples, como iremos ver em seguida.

O Visual Studio vai nos mostrar o Designer do edmx, junto com as três entidades já adicionadas. Ver Figura 8.

designer_edmx

Figura – 8 – Design

Vamos entender um pouco sobre o que na verdade é o edmx. O edmx é um arquivo XML, no qual vai constar o mapeamento para o nosso modelo físico. Ele é composto por três arquivos internos, que são desmembrados em runtime, que são: SSDL (Storage Model Content), o CSDL (Conceptual Model Content) e o MSL (Mapping Model Content). Segue abaixo o conteúdo de cada uma destas partes do edmx (retirado da MSDN Library).

  • SSDL (Storage Model): Descreve o banco de dados no qual estaremos trabalhando os dados.
  • CSDL (Conceptual Model): Descreve os nossos objetos no modelo, sejam entidades, tipos complexos, navigation properties.
  • MSL (Mapping Model): Descreve o mapeamento objeto-relacional (ORM), para que o SSDL e o CSDL possam se relacionar corretamente.
Criação do WCF Data Service

O próximo passo é adicionar um novo item ao projeto ExemploCRUD.Web. Menu => Project => “Add New Item”, selecione no grupo de templates “Web” o item “WCF Data Service”, e nomeei-o ExemploDataService, conforme figura 9.

exemploDataService

Figura 9 – ExemploDataService

WCF Data Services é uma forma de expor um modelo de dados do Entity Framework através de uma interface REST. O DataService é uma extensão do WCF, isto é, pode ser hospedado como qualquer serviço WCF. É uma tecnologia que visa facilitar o acesso a dados tanto de aplicações Web comuns, como AJAX, Silverlight e .NET.

Para expor os dados via WCF Data Services, é preciso que se tenha uma fonte de dados que suporte consultas utilizando LINQ, isto é, que implemente IQueryable/IUpdatable. Resumidamente, a aplicação pede um endereço para o serviço, e este endereço é traduzido como uma consulta LINQ para que então, o provedor de dados retorne os dados de interesse.

Parece meio confuso, mas na verdade o WCF Data Service nos dá as seguintes possibilidades:

  • Fornece uma API que nos permite criar e consumir dados através de HTTP, utilizando serviços RESTful;
  • Suporte a todas as operações de banco de dados através de URI;
  • Capacidade de expor um Modelo de Entidade através de um URI;
  • Suporte CRUD;
  • Pode ser consumido por qualquer aplicação em diferentes tipos de clientes como Windows, SilverLight, Web, AJAX e Console.

Vamos editar o nosso WCF Data Service (ExemploDataService.svc.cs), e deixa-lo de acordo com a listagem 1:

1. using System.Data.Services;
 2. using System.Data.Services.Common;
 3.
 4. namespace ExemploCRUD.Web
 5. {
 6. public class ExemploDataService : DataService<ExemploEntities>
 7. {
 8. // This method is called only once to initialize service-wide policies.
 9. public static void InitializeService(DataServiceConfiguration config)
 10. {
 11. // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
 12. // Examples:
 13. config.SetEntitySetAccessRule("*", EntitySetRights.All);
 14. config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
 15. config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
 16. }
 17. }
 18. }

Listagem 1 – ExemploDataService.svc.cs

  • Na linha 6, é apenas informado a nossa classe de fonte de dados, ExemploEntities;
  • Nas linhas 13 e 14, vamos descomentá-la e alterar para permitir acesso a todas as regras e operações.

Feito isso compile a sua aplicação, e com o botão direito do mouse em cima do arquivo ExemploDataService.svc, selecione a opção “View in Browser”. Se tudo ocorreu corretamente até aqui, você verá os dados de um arquivo xml mostrando as tabelas do nosso banco de dados. Ver figura 10.

exemploDataService_inBrowser

Figura 10 – Rodando o Serviço WCF

Até aqui tudo certo, o próximo passo é incluir uma “Service Reference” no projeto ExemploCRUD. Para isso clique com o botão direito do mouse no projeto ExemploCRUD e selecione a opção “Add Service Reference”.

Feito isso abrirá uma janela (ver figura 11), clique no botão “Discover”, de o nome de “ExemploServiceReference” e de OK. Isso incluirá uma referência ao nosso serviço WCF.

exemploServiceReference

Figura 11 – ExemploServiceReference

Interface

Por questões didáticas o exemplo não utilizará nenhum pattern. A listagem 2 mostra o código final para a MainPage.xaml. Trata-se de uma interface simples, como pode ser conferida na figura 12.

<UserControl x:Class="ExemploCRUD.MainPage"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
 mc:Ignorable="d"
 d:DesignHeight="300" d:DesignWidth="400">
 <Grid x:Name="LayoutRoot" Background="White">
 <StackPanel Margin="10">
 <sdk:DataGrid AutoGenerateColumns="False" x:Name="gridData" Height="400" Width="800" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" >
 <sdk:DataGrid.Columns>
 <sdk:DataGridTemplateColumn Header="Nome">
 <sdk:DataGridTemplateColumn.CellTemplate>
 <DataTemplate>
 <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 </DataTemplate>
 </sdk:DataGridTemplateColumn.CellTemplate>
 </sdk:DataGridTemplateColumn>
 <sdk:DataGridTemplateColumn Header="Email">
 <sdk:DataGridTemplateColumn.CellTemplate>
 <DataTemplate>
 <TextBlock Text="{Binding PersonEmails[0].Email}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 </DataTemplate>
 </sdk:DataGridTemplateColumn.CellTemplate>
 </sdk:DataGridTemplateColumn>
 <sdk:DataGridTemplateColumn Header="Tipo de Email">
 <sdk:DataGridTemplateColumn.CellTemplate>
 <DataTemplate>
 <TextBlock Text="{Binding PersonEmails[0].EmailType}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 </DataTemplate>
 </sdk:DataGridTemplateColumn.CellTemplate>
 </sdk:DataGridTemplateColumn>
 <sdk:DataGridTemplateColumn Header="Telefone">
 <sdk:DataGridTemplateColumn.CellTemplate>
 <DataTemplate>
 <StackPanel Orientation="Horizontal">
 <TextBlock Text="{Binding PersonPhones[0].DDI}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 <TextBlock Text="{Binding PersonPhones[0].DDD}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 <TextBlock Text="{Binding PersonPhones[0].Number}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 <TextBlock Text="{Binding PersonPhones[0].Ext}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 </StackPanel>
 </DataTemplate>
 </sdk:DataGridTemplateColumn.CellTemplate>
 </sdk:DataGridTemplateColumn>
 <sdk:DataGridTemplateColumn Header="Tipo de Telefone">
 <sdk:DataGridTemplateColumn.CellTemplate>
 <DataTemplate>
 <TextBlock Text="{Binding PersonPhones[0].PhoneType}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"/>
 </DataTemplate>
 </sdk:DataGridTemplateColumn.CellTemplate>
 </sdk:DataGridTemplateColumn>
 </sdk:DataGrid.Columns>
 </sdk:DataGrid>
 <StackPanel Width="800" HorizontalAlignment="Center" Margin="5">
 <StackPanel Orientation="Horizontal">
 <TextBlock Text="Nome:" Width="100" Margin="5" />
 <TextBox x:Name="txtName" Text="{Binding SelectedItem.Name, ElementName=gridData}" Width="200" Margin="5" />
 </StackPanel>
 <StackPanel Orientation="Horizontal" >
 <TextBlock Text="Email:" Width="100" Margin="5" />
 <TextBox x:Name="txtEmail" Text="{Binding SelectedItem.PersonEmails[0].Email, ElementName=gridData}" Width="200" Margin="5" />
 <TextBlock Text="Tipo de Email:" Width="100" Margin="5" />
 <TextBox x:Name="txtEmailType" Text="{Binding SelectedItem.PersonEmails[0].EmailType, ElementName=gridData}" Width="200" Margin="5" />
 </StackPanel>
 <TextBlock Text="Telefone" Margin="5" HorizontalAlignment="Left"/>
 <StackPanel Orientation="Horizontal" >
 <TextBlock Text="DDI:" Width="100" Margin="5" />
 <TextBox x:Name="txtDDI" Text="{Binding SelectedItem.PersonPhones[0].DDI, ElementName=gridData}" Width="200" Margin="5" />
 <TextBlock Text="DDD:" Width="100" Margin="5" />
 <TextBox x:Name="txtDDD" Text="{Binding SelectedItem.PersonPhones[0].DDD, ElementName=gridData}" Width="200" Margin="5" />
 </StackPanel>
 <StackPanel Orientation="Horizontal" >
 <TextBlock Text="Número:" Width="100" Margin="5" />
 <TextBox x:Name="txtPhoneNumber" Text="{Binding SelectedItem.PersonPhones[0].Number, ElementName=gridData}" Width="200" Margin="5" />
 <TextBlock Text="Ramal:" Width="100" Margin="5" />
 <TextBox x:Name="txtExt" Text="{Binding SelectedItem.PersonPhones[0].Ext, ElementName=gridData}" Width="200" Margin="5" />
 </StackPanel>
 <StackPanel Orientation="Horizontal">
 <TextBlock Text="Tipo:" Width="100" Margin="5" />
 <TextBox x:Name="txtPhoneType" Text="{Binding SelectedItem.PersonPhones[0].PhoneType, ElementName=gridData}" Width="200" Margin="5" />
 </StackPanel>
 </StackPanel>
 <StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Center">
 <Button x:Name="btnInsert" Content="Incluir" Click="btnInsert_Click" Width="100" Height="26"/>
 <Button x:Name="btnEdit" Content="Editar" Click="btnEdit_Click" Width="100" Height="26"/>
 <Button x:Name="btnDelete" Content="Deletar" Click="btnDelete_Click" Width="100" Height="26"/>
 <Button x:Name="btnLoad" Content="carregar" Click="btnLoad_Click" Width="100" Height="26"/>
 </StackPanel>
 </StackPanel>
 </Grid>
 </UserControl>

Listagem 2 – Código Final da MainPage.xaml

view

Figura 12 – Interface do Usuário

As Quatro Operações

As operações CRUD (acrónimo de Create, Read, Update e Delete em Inglês) são operações básicas, fundamentais para a manipulação da base de dados e importantes, pois requerem, sem a utilização de um ORM como o Entity Framework, trabalho que em muitas vezes é complexo.

O funcionamento de todas as operações são muito semelhantes. Criada uma nova instância da nossa entidade (neste exemplo “ExemploEntities”), onde a mesma herda de uma classe da Entity Framework chamada ObjectContext, que é a classe primária e responsável por gerir as informações.

Os serviços WCFs podem ser consumidos de duas formas:

  • Síncrona: Quando uma requisição é feita, o processo remetente é bloqueado até que a recepção correspondente seja realizada, ou seja, a aplicação ficará bloqueada aguardando o resultado;
  • Assíncrona: A operação será realizada em um thread secundária, permitindo que a aplicação continue trabalhando enquanto o serviço é executado. No Silverlight é possível apenas a realização de operações assíncronas.
Inserindo Registros

Na listagem 3 é apresentado o código responsável pelo o trabalho de inserção de novos registros no banco de dados.

Para inserir novos registos, neste caso uma nova pessoa, criamos uma nova instância da nossa entidade onde é solicitado o endereço do serviço, é a mesma url da figura 10. Criamos um novo Person. Depois adicionamos o objeto através do método AddToPeople(person) e, finalmente, executamos o método BeginSaveChanges que irá neste caso inserir um novo registo no banco de dados. O método EndSaveChanges é o responsável por nos dar o retorno da ação no banco.

1. ExemploEntities entities = new ExemploEntities(new Uri("http://localhost:56903/ExemploDataService.svc/"));
 2.
 3. Person person = new Person() { ID = Guid.NewGuid(), Name = this.txtName.Text };
 4.
 5. entities.AddToPeople(person);
 6.
 7. entities.BeginSaveChanges((result) =>
 8. {
 9. entities.EndSaveChanges(result);
 10. }, null);

Listagem 3 – Insert

Editando Registros

Na listagem 4 é apresentado o código responsável pelo trabalho de edição dos registros do banco de dados.

Para editar os registros, igualmente a inserção nós criamos uma nova instância entidade, criamos um novo Person, e informamos que o ID é o mesmo do objeto selecionado na nossa grid e que o nome é o informado no textbox. Depois devemos informar ao entity framework qual tabela será alterada, isso fazemos através do método AttachTo, logo após é passado o novo objeto com o uso do método UpdateObject e finalmente igual a inserção, executamos o método BeginSaveChanges que irá atualizar os dados da nossa pessoa e o método EndSaveChanges que novamente é o responsável por nos dar o retorno da ação no banco.

1. ExemploEntities entities = new ExemploEntities(new Uri("http://localhost:56903/ExemploDataService.svc/"));
 2.
 3. Person person = new Person() { ID = ((Person)this.gridData.SelectedItem).ID, Name = this.txtName.Text };
 4.
 5. entities.AttachTo("People", person);
 6. entities.UpdateObject(person);
 7.
 8. entities.BeginSaveChanges((result) =>
 9. {
 10. entities.EndSaveChanges(result);
 11. }, null);

Listagem 4 – Update

Deletando Registros

Na listagem 5 é apresentado o código para a exclusão dos registros no banco de dados.

A única diferença desse método para o de edição é o uso do método DeleteObject, que é o responsável por informar qual objeto será deletado, apenas a chave primária é necessário informar, no nosso caso é o ID. Todo o resto funciona nos mesmos moldes da Edição.

1. ExemploEntities entities = new ExemploEntities(new Uri("http://localhost:56903/ExemploDataService.svc/"));
 2.
 3. Person person = new Person() { ID = ((Person)this.gridData.SelectedItem).ID };
 4.
 5. entities.AttachTo("People", person);
 6. entities.DeleteObject(person);
 7.
 8. entities.BeginSaveChanges((result) =>
 9. {
 10. entities.EndSaveChanges(result);
 11. }, null);

Listagem 5 – Delete

Listando Registros

Na listagem 6 apresenta o código para listar os dados da tabela Person, note que esse método se difere dos outros.

Novamente criamos uma nova instância da nossa entidade e agora com o uso do LINQ to Entities, vamos selecionar todos os registros de Person. Note que eu uso um Expand para que o mesmo nos traga os dados da relação com PersonEmail e PersonPhone.

Outra particularidade é o uso do método BeginExecute, que irá executar a query e o método EndExecute que nos trará o resultado da pesquisa, neste caso trata-se de um IEnumerable<Person>.

 1. ExemploEntities entities = new ExemploEntities(new Uri("http://localhost:56903/ExemploDataService.svc/"));
 2.
 3. var query = (from A in entities.People.Expand("PersonEmails, PersonPhones")
 4. select A) as DataServiceQuery<Person>;
 5.
 6. query.BeginExecute((result) =>
 7. {
 8. this.gridData.ItemsSource = query.EndExecute(result).ToList();
 9. }, null);

Listagem 6 – Load

Conclusão

O Entity Framework é uma excelente opção para se trabalhar com bases de dados. Simples de utilizar permite-nos trabalhar apenas com objetos, intellisense, nos resolve inúmeros problemas habituais quando se trabalha diretamente com o banco de dados e nos possibilita o desuso do SqlCommands, SqlConnections, etc.

O download da aplicação pode ser feito através desse link.

Link de Apoio:

Fontes:

Deixe uma resposta

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

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s