Entity Framework 5 - Apresentando e usando Spatial Data
Hoje eu vou escrever sobre um novo recurso do Entity Framework, disponível a partir da versão 5, (a versão 6.0 já esta em beta) conhecido como Spatial Data ou Dados geográficos.
A versão 5 do Entity Framework, a partir de agora citada apenas como EF5, além de um novo modelo de mapeamento Code First (Sem Designer nem XML), nova APi DBContext e melhorias no desempenho trouxe as seguintes novidades:
Spatial Data - Dados geográficos agora podem ser expostos em seu modelo usando o DbGeography e os tipos DbGeometry. Com isso podemos ter um campo do tipo DbGeography e através do namespace System.Data.Spatial manipular dados geográficos informando as coordenadas latitude e longitude;
Migrations - Este o recurso permite realizar alterações em nosso modelo de entidades e ter a atualização automática do banco de dados refletindo essas mudanças sem perder os dados;
Table Value Functions (TVF) - Este recurso permite mapear TVFs tanto para entidades como para tipos complexos no EF5; (TVFs são funções definidas pelo usuário (UDF), que vivem na base de dados alvo e cujo tipo de retorno é uma tabela.)
Enums - Permite que você tenha propriedades de enumeração - enum - em suas classes de entidade; assim o Code First já as reconhece e as implementa no database.
O Code First agora detecta se você tem o LocalDB ou o SQL Express disponível para criar novas bases de dados.O Visual Studio 2012 inclui o LocalDB, enquanto Visual Studio 2010 inclui o SQL Express.
Outro detalhe importante: Agora o Entity Framework é Open Source, e, tem o código aberto e esta esperando pela nossa contribuição... (ASP .NET MVC, ASP .NET Web API e Razor também são projetos Open Source...)
Obs: Instalar o Entity Framework agora é bem simples. Abra o Package Manger Console digite : Install-Package EntityFramework e pronto!
Os dados espaciais representam informações sobre o local físico e a forma de objetos geométricos. Esses objetos podem ser locais de pontos ou objetos mais complexos como países, estradas ou lagos.
O SQL Server suporta dois tipos de dados espaciais: o tipo de dados geometry e o tipo de dados geography.
O Entity Framework suporta trabalhar com dados espaciais/geográficos através das classes DbGeography e DbGeometry. Essas classes se baseiam em funcionalidades especificas do banco de dados fornecidas pelo Entity Framework provider. Nem todos os provedores dão suporte aos dados espaciais e aqueles que dão suporte podem ter pré-requisitos adicionais.
Neste artigo eu vou mostrar um exemplo simples e prático de utilização dos dados geográficos com Code-First em uma aplicação VB .NET usando o Visual Studio Express 2012 for Windows Desktop e o Entity Framework com Code-First. (O banco de dados usado será o LocalDB)
Iremos criar uma aplicação onde iremos gerar um banco de dados com informações de alguns hotéis como nome, cidade e localização geográfica usando as coordenadas de latitude e longitude (obtidas do Google Maps).
Usando Spatial Data com Code-First
Agora vamos instalar o Entity Framework 5 via Nuget.
No menu TOOLS clique em Library Package Manager e a seguir em Package Manager Console;
No Package Manager Console digite : Install-Package EntityFramework e tecle ENTER;
O Entity framework 5 deverá ser instalado e adicionado ao nosso projeto conforme mostra a figura acima.
Definindo o modelo usando Code-First
Ao utilizar o modelo de desenvolvimento Code-First geralmente começamos definindo as classes do nosso modelo conceitual ou seja do nosso domínio. Para o exemplo do artigo irei definir a classe Hotel com as propriedades : HotelID, Nome, Cidade e Localizacao :
Clique no menu PROJECT e a seguir em Add Class e informe o nome Hotel.vb a seguir defina o código abaixo para a classe Hotel:
Imports System.Data.SpatialPublic Class Hotel Public Property HotelID As IntegerPublic Property Nome As String Public Property Cidade As String Public Property Localizacao As DbGeography End Class
|
A propriedade Localizacao e do tipo DbGeography e para poder esse tipo temos que incluir o namespace System.Data.Spatial.
Agora temos que definir a classe que deriva de DbContext e expõe
propriedades DbSet(Of TEntity)
As propriedades DbSet(Of TEntity) permitem que o contexto reconheça quais
tipos desejamos incluir em nosso modelo.
Uma instância do tipo derivado DbContext gerencia os objetos de entidade
durante o tempo de execução, o qual inclui popular os objetos com dados de um
banco de dados, controlar as alterações, e persistir os dados no banco de dados.
Os tipos DbContext e DbSet são definidos no
assembly EntityFramework que foi adicionado e referenciando quando instalamos o EF via Nuget.
Clique no menu PROJECT e a seguir em Add Class e informe o nome HotelContext.vb a seguir defina o código abaixo para a classe HotelContext:
Imports System.Data.EntityPublic Class HotelContext Inherits DbContextPublic Property Hoteis() As DbSet(Of Hotel) End Class
|
Observe a referência ao namespace System.Data.Entity e que a classe HotelContext herda de DbContext.
Definindo a interface
Vamos agora definir uma interface bem simples em nosso projeto usando o formulário form1.vb e incluindo os seguintes componentes:
Disponha os controles conforme o leiaute exibido na figura abaixo:
Defina o seguinte namespace no início do formulário form1.vb:
Imports
System.Data.SpatialAgora vamos definir o código do evento Click do botão de comando - Criar Dados com o EF5- conforme abaixo:
Private Sub btnCriarDados_Click(sender As Object, e As EventArgs) Handles btnCriarDados.ClickCriarDados() End Sub
|
O código da rotina CriarDados() é visto a seguir:
Private Sub CriarDados() Using contexto = New HotelContext() contexto.Hoteis.Add(New Hotel() With { _ .Nome = "Hotel Arpoador", _ .Cidade = "Salvador", _ .Localizacao = DbGeography.FromText("POINT(-12.983148 -38.521729)") _ }) contexto.Hoteis.Add(New Hotel() With { _ .Nome = "Hotel Sereia do Mar", _ .Cidade = "Guaruja", _ .Localizacao = DbGeography.FromText("POINT(-23.926013 -46.300049)") _ }) contexto.Hoteis.Add(New Hotel() With { _ .Nome = "Hotel Nosso Cantinho", _ .Cidade = "Rio de Janeiro", _ .Localizacao = DbGeography.FromText("POINT(-22.897683 -43.24585)") _ }) contexto.Hoteis.Add(New Hotel() With { _ .Nome = "Hotel Candeias", _ .Cidade = "Belo Horizonte", _ .Localizacao = DbGeography.FromText("POINT(-19.932041 -43.970948)") _ }) contexto.Hoteis.Add(New Hotel() With { _ .Nome = "Hotel America", _ .Cidade = "Goiânia", _ .Localizacao = DbGeography.FromText("POINT(-16.678293 -49.288331)") _ }) contexto.SaveChanges() End Using End Sub
|
Neste código estou incluindo informações para 5 hotéis na tabela Hotels. Observe que o tipo de dado Localizacao é do tipo DbGeography e esta sendo informando com as coordenadas, latitude e longitude, que representa a localização do hotel no Google Maps.
O método SaveChanges irá criar o banco de dados e persistir as informações na tabela Hotels.
Agora temos o código do evento Click do botão de comando - Exibir Dados Criados :
Private
Sub
btnExibirDados_Click(sender
As
Object,
e As
EventArgs)
Handles
btnExibirDados.Click ExibirDados() End Sub |
O código da rotina ExibirDados() é dado a seguir:
Private Sub ExibirDados() Using contexto = New HotelContext() Dim locais = From loc In contexto.Hoteis Select loc lsbDados.Items.Clear() For Each hot In locais lsbDados.Items.Add(hot.Nome + " - " + hot.Cidade + " - " + hot.Localizacao.ToString()) Next End Using End Sub
|
No código acima estou selecionando os dados da entidade Hotels exibindo-as em um ListBox usando uma consulta LINQ.
Para localizar um hotel mais próximo da minha localização com base nas coordenadas (latitude/longitude) temos o código abaixo no evento Click do botão : Encontrar Hotel mais perto:
Private Sub btnLocalizar_Click(sender As Object, e As EventArgs) Handles btnLocalizar.Click Using contexto = New HotelContext Dim coordenadas As String = txtLocalizacao.Text Dim minhaLocalizacao = DbGeography.FromText("POINT(" + coordenadas + ")") 'Brasilia Dim hotel = (From ht In contexto.Hoteis Order By ht.Localizacao.Distance(minhaLocalizacao) _ Select ht).FirstOrDefault lblResposta.Text = "O hotel mais perto desta localização é : " + vbCrLf + hotel.Nome + vbCrLf + hotel.Cidade + vbCrLf + hotel.Localizacao.Latitude.ToString + "-" + hotel.Localizacao.Longitude.ToString End Using End Sub
|
Note que estamos o método Distance da classe DbGeography para calcular a distância entre os pontos mais próximos das coordenadas da minha localização. No resultado estou usando as propriedades Latitude e Longitude da mesma classe para exibir os respectivos valores das coordenadas.
Nota: Lembre que a classe DbGeography representa dados em um sistema de coordenadas geodésicas
No menu VIEW clique em DataBase Explorer e a seguir clique com o botão direito sobre Data Connections e selecione Add Connection;
Informe o nome do servidor de banco de dados como LocalDB\v11.0 e abra a caixa dropdownlist em Select ou enter a database name;
Perceba que entre os bancos de dados listados podemos identificar um contendo o nome da nossa solução e do nosso contexto. Esse é o banco de dados que foi criado automaticamente pelo Code-First:
Observe que o banco de dados foi criado com o nome EF5_SpatialData.HotelContext que é o formato padrão de nomes usado : Nome da Solucao+Nome do Contexto
Selecionando o banco de dados e expandindo os objetos Tables vemos a tabela Hotels; clicando bom o botão direito do mouse sobre ela e selecionando Show Table Data vermos os dados que foram persistidos pela Code-First.
Conferimos desta a forma a utilização do novo recurso Spatial Data no Entity Framework 5. Pense nas possibilidades...
Pegue o projeto completo aqui: EF5_SpatialData.zip (sem a referência ao EF5)
Mar 1:5
E saíam a ter com ele toda a terra da Judéia, e todos os moradores de Jerusalém; e eram por ele batizados no rio Jordão, confessando os seus pecados.Mar 1:6
Ora, João usava uma veste de pelos de camelo, e um cinto de couro em torno de seus lombos, e comia gafanhotos e mel silvestre.Mar 1:7
E pregava, dizendo: Após mim vem aquele que é mais poderoso do que eu, de quem não sou digno de, inclinando-me, desatar a correia das alparcas.Referência:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#