Windows Azure Storage

Vivemos uma fase bastante interessante, na qual presenciamos a crescente expansão dos serviços providos pela nuvem. Dia após dia, novos serviços surgem e ficamos estatelados, imaginando: “Nossa! Eu podia ter usado isso naquele projeto!” ou então “Nossa! Como eu consegui trabalhar até agora sem isso?”.

Na minha humilde opinião, logo mais, conhecer os serviços providos pela nuvem será tão importante quando saber conectar sua aplicação a um banco de dados ou jogar uma mensagem em um serviço de mensageria. Trabalhar com a nuvem não será um diferencial, mas um conhecimento tido como requisito básico.

image

Leia mais »

Construindo camadas de acesso a dados – Parte II – Identity Field

Dentro dos diferentes patterns de criação de camadas de acesso dados alguns deles não estão diretamente associados à construção de nossos repositórios, mas estão associados com a adequação da estrutura de nossas entidades a um determinado objetivo.

Este post é sobre um pattern chamado Identity Field.

O padrão Identity Field instrui a utilização de uma propriedade que funcione como chave de identificação de cada entidade das demais, independente do seu tipo de dados, tabela na qual estão salvos ou estrutura.

O objetvo desta chave de identificação é basicamente funcionar como identificador global, que ao contrário dos valores de campos que são chaves primárias (que geralmente são baseados em tipos inteiros, auto-incrementais e que podem se repetir em outras tabelas), agregue uma identificação única daquela tupla no banco de dados e no sistema.

Leia mais »

Construindo camadas de acesso a dados

A principal motivação para o uso de uma camada de acesso a dados (data access layer, DAL) em nossa aplicação é manter os códigos (e as tecnologias) de acesso a dados encapsulados em uma camada que fique responsável por comunicar-se com a fonte de dados, persistindo e recuperando dados de nossas entidades.

Uma camada de acesso a dados deve fornecer recursos para criação, leitura, atualização e exclusão de dados, além de controles de transação, segurança, mapeamento, concorrência, e outros. A sua criação favorece o uso de uma administração centralizada que separa o comportamento da camada de negócios das lógicas de acesso a fontes de dados e serviços.

data-net

Leia mais »

Integrando MongoDB com .Net e LINQ

Olá!

Na última sexta-feira (13 de Julho de 2012), estive presente no MongoDB São Paulo 2012. Um evento organizado pela 10Gen sobre o uso do MongoDB. Para quem não sabe o MongoDB é um banco de dados No-SQL, isto é, não trabalha com o paradigma relacional, não trabalha com colunas e nem linhas. A persistência dos dados é toda baseada na estrutura das entidades de suas classes. Isto é bastante favorável, pois não exige a existência de uma estrutura rígida baseada em um schema. Algum tempo atrás eu fiz uma série de experimentos com o Db4Objects (https://ferhenriquef.com/?s=db4o), um banco de dados orientado a objetos que funciona de forma parecida.

Um adendo: quando fiz a faculdade de Sistemas de Informação, na Universidade Presbiteriana Mackenzie, eu tive a possibilidade de escolher uma ênfase para o meu curso, e no caso escolhi a ênfase em Banco de Dados. Então, isso explica alguns dos meus posts e alguns dos experimentos neste blog. Sou vidrado em tecnologias diferentes de armazenamento de dados, mas acho que isso todos já perceberam.

mongoNet

Leia mais »

DbContext e o ObjectContext – Não deixe seus dados em memória!

O DbContext e o ObjectContext são duas classes responsáveis por gerenciar e acompanhar alterações em instâncias de classes no modelo, estas classes também gerenciam a conexão e o contexto de transação das operações com o banco de dados.

É importante assegurar que qualquer recurso associado com estes objetos seja limpo da memória quando não mais necessários, pois ao longo de cada execução é mantido um CACHE das instâncias de objetos recuperadas nas consultas. Se mantivermos a instância de nosso contexto por muito tempo ativa, executando consultas atrás de consultas, corremos o risco de consumir mais memória do que o necessário.

Para resolver esta questão, tanto a classe DbContext quanto a classe ObjectContext implementam a interface IDisposable, que inclui o método Dispose(), responsável por eliminar recursos utilizados pela instância corrente que não sejam mais necessários.

Leia mais »

SQL Azure – Consultando dados

O SQL Azure é um conjunto de serviços que oferece capacidade de processamento e armazenamento de dados relacionais na nuvem. É a ferramenta que devemos utilizar para armazenarmos dados relacionais de nossa aplicação na plataforma Windows Azure.

No post anterior (https://ferhenriquef.com/2012/04/25/como-criar-um-banco-de-dados-no-sql-azure/) discutimos sobre como criar uma base de dados no SQL Azure, neste post vou demonstrar como acessar o SQL Azure.

Para acessar o SQL Azure não precisamos de nenhum SDK ou configuração especial, apenas precisamos modificar nossa connection string, definindo como server o nome do nosso servidor no Azure.Leia mais »

Uso de Include em consultas com o Entity Framework Code First

Um tópico muito discutido nos fóruns de acesso a dados (http://social.msdn.microsoft.com/Forums/pt-BR/adoptpt/threads) e LINQ (http://social.msdn.microsoft.com/Forums/pt-BR/linqpt/threads) é o uso de Lazy Load no Entity Framework.

O Lazy Load (ou Lazy Loading) nada mais é do que um mecanismo adotado pelos frameworks de persistência a dados para carregar as informações sobre demanda, isto é, carregar em memória apenas os dados de propriedades que não sejam relacionamentos para outras entidades. Este tipo de recurso minimiza o consumo de memória, o trafego de dados pela rede e os recursos de consulta do banco de dados, além de tornar a consulta mais rápida.Leia mais »

EntityTypeConfiguration

Quando utilizamos a Fluent API para configuração do mapeamento de nosso banco de dados, corremos o risco de tornar o método OnModelCreating muito extenso e complexo.

Para evitar este cenário podemos criar uma classe que herde de EntityTypeConfiguration e que descreva qual a configuração de nosso mapeamento.

A classe EntityTypeConfiguration permite o mapeamento indvidual de nossas entidades, tornamos o comportamento de nosso método OnModelCreating mais simples e encapsulando o mapeamento de nossas entidades em classes próprias para isso.Leia mais »

EF41 – Inicializadores de Banco de Dados

Ao trabalharmos com o Entity Framework Code First nos deparamos com diversas convenções. Uma das mais importantes é processo de construção do banco de dados. O Entity Framework 4.1 nos fornece nativamente três inicializadores de banco de dados, sendo eles:

DropCreateDatabaseIfModelChanges:apaga e recria o banco de dados toda vez que alguma alteração no modelo de classes for identificada. Observação: se a tabela EdmMetadata não estiver sendo criada no banco de dados (através da remoção da convention IncludeMetadataConvention), então está opção não irá funcionar e irá disparar uma Exception do tipo NotSupportedException.

CreateDatabaseIfNotExists:cria o banco de dados se o mesmo não existir, se o modelo de classes sofrer alguma alteração será disparada uma exception.

DropCreateDatabaseAlways:apaga e recria o banco de dados sempre, mesmo que nenhuma alteração no modelo de classes tenha sido feita.Leia mais »

Construindo sua camada de acesso a dados com o Entity Framework 4.1

O Entity Framework 4.1(EF41) Code First veio para ajudar os desenvolvedores no processo de construção da camada de acesso a dados de suas aplicações. Ao contrário dos demais modelos do Entity Framework, o modelo Code First tem por objetivo criar o banco de dados seguindo como base a estrutura de nossas classes – os demais modelos, conhecidos como Table First, baseavam a criação das classes no modelo existente em nosso banco de dados. A vantagem da utilização do Code First é a possibilidade de criar um modelo de classes muito mais próximo a nossa necessidade, ao contrário das abordagens anteriores que produziam um modelo de classe “adaptado” de nossa estrutura de banco de dados.

Neste exemplo vamos discutir os modos de implementação de diferentes modelos de relacionamentos (e.g. um-para-muito, muitos-para-muitos, um-para-um) utilizando o ADO.Net Entity Framework 4.1. Além disso, quero mostrar algumas novas features e dar algumas dicas de como nos adequar ao Entity Framework 4.1.

Vamos começar! Alegre

Obs.: Para fazer download do código-fonte acesse este link: http://code.msdn.microsoft.com/Construindo-sua-camada-de-de659425.

1 – Nosso projeto de teste

Para este teste criaremos um cadastro de Clientes, Fabricantes, Produtos e Ordens de Compra. Neste modelo um cliente pode efetuar diversas ordens de compras, sendo que cada comprar pode conter um ou mais produtos, onde cada produto pode estar atrelado a uma ou mais ordens de compra. Além disso, um produto obrigatoriamente contém um fabricante. Nosso diagrama de classes será o seguinte:

diagrama

2 – Camadas da aplicação

Para este exemplo adotei os design patterns MVC e DAO. Os projetos estão dispostos como a imagem a seguir:

Projects

Commerce.Controler: corresponde a camada de controle de nossa aplicação.

Commerce.Entity: possui todas as entidades lógicas de nossa aplicação, além das interfaces que devem ser implementadas pelas demais camadas.

Commerce.Data: responsável pela funcionalidade de armazenamento das informações, esta camada engloba todo o uso do Entity Framework 4.1, diminuindo a dependência do projeto a um tecnologia. Isso permite a fácil manutenção e alteração da tecnologia, sem gerar impactos globais por toda a aplicação.

Commerce.Console: camada de apresentação e consumo dos recursos.

3 – Estratégia de criação da base de dados

Para definir a estratégia de criação do banco de dados fazemos uso de inicializadores.A estratégia default é a DropCreateDatabaseIfModelChanges, que apaga o banco de dados e o recria, além dessa estratégia ainda existem outras duas, sendo elas: DropCreateDatabaseAlways e CreateDatabaseIfNotExists. O time de produto do ADO.Net trabalha hoje em um projeto chamado Code First Migration, que trata do processo de adequação do modelo do banco de dados com as atualizações de suas entidades, sem que seja necessário apagar e recriar o banco de dados. Para fazer uso dos inicializadores de bancos de dados crie em seu DataContext um construtor que defina a estratégia de criação da base de dados como a seguir:

SetInitializer

4 – Remoção de convenções do Entity Framework 4.1

Para efetuar o mapeamento automático de nossas tabelas, o EF41 adota algumas convenções de nomenclatura, tipos de dados, e outros recursos. Para adicionar ou remover convenções devemos sobrescrever o método OnModelCreating de nosso DataContext. Em nosso exemplo removerei duas convenções: IncludeMetadataConvention, que evita a criação da tabela EdmMetada, que é uma tabela que contém um código uma única linha com um código hash utiliza para verificar se o modelo de nosso código é o mesmo do modelo de nosso banco de dados (mais informações aqui: http://blog.oneunicorn.com/2011/04/08/code-first-what-is-that-edmmetadata-table/); e PluralizingTableNameConvention, que é um atributo que evita que a nome das tabelas seja pluralizado, isto é, se você possui uma entidade chamada Carro, a tabela criada automaticamente no banco de dados se chamará Carro, e não Carros como a convenção do EF41 faz.

Conventions

5 – Tipos complexos

É bastante comum em nossas aplicações a necessidade de utilizarmos atributos que apenas servem como “agrupadores” de dados, e que na verdade não deve ser mapeamos em uma única tabela dedicada a eles. Podemos adotar como exemplo um tipo de dados Endereço. Uma classe chamada Endereço é bastante importante para agrupar informações de localidade, mas não possui características que exijam mapeamento para uma tabela dedicada exclusivamente para isso. Diante deste cenário devemos fazer uso do atributo ComplexType. Este atributo quando utilizado indica que nossa classe é um tipo complexo, que não deverá ser persistido em uma tabela própria, e que estará vinculado a atributo de alguma classe. Podemos indicar que uma classe é um tipo complexo de duas maneiras, sendo elas:

2.1 – No corpo da classe, indicando através do atributo ComplexType:

ComplexType01

2.2 – Indicando o tipo complexo em nosso DataContext, dentro do método OnModelCreating:

ComplexType02

Ultimamente tenho pensado que é mais interessante configurar o mapeamento de nossas classes dentro do DataContext do que em nossas classes através da utilização de atributos. Acredito que essa é a melhor forma, pois nosso projeto de entidades ficará livre de mais dependências, necessitando apenas de recursos nativos do Framework .

6 – Entidade base para persistência de dados em fontes de dados

É interessante, ao implementarmos nossas entidades, a criação de uma entidade base que defina atributos obrigatórios para todas as entidades. Neste exemplo criei uma entidade chamada DataEntity que contém três atributos: Id, atributo do tipo inteiro que servirá como chave primária de nossas entidades na base de dados; GlobalId, atributo do tipo GUID que fornecerá um identificador global a nossos registros dentro da base de dados; e Created, atributo do tipo DateTime que informará a data de criação de nossas entidades.

dataEntity

A utilização dessa classe como entidade base exige duas implementações em nossas entidades:

1 – Herança

Herança

2 – Invoque ao construtor da classe base em nossas entidades

construtor

7 – Interface como contrato para os repositórios

Para implementação dos repositórios criei uma interface com um conjunto de métodos obrigatórios que se espera de um repositório.

IRepository

Nessa interface temos as assinaturas:

void Save(T target): este método deve ser responsável pela inclusão e atualização dos dados na base de dados. Uma vez executado deve garantir que os dados serão inclusos ou atualizados conforme a entidade passada por parâmetro.

void Delete(T target): método de exclusão de registros da base de dados. Quando invocado, deve apagar o registro passado por parâmetro da base de dados.

T GetById(int id): método que deve retornar o registro na base de dados que contiver em sua chave primária o valor passado por parâmetro.

T GetByGlobalId(Guid id): gosto bastante de utilizar um campo UNIQUEIDENTIFIER em meus registros, pois atribuímos ao registro uma chave de identificação única que o torna único em todo o banco de dados, independente de sua localização – assim como propostos em bases de dados orientadas a objetos.

IEnumerable<T> GetAll(): deve retornar todos os registros existentes na base de dados para a entidade consultada.

IEnumerable<T> ExecuteQuery(Func<T, bool> expression): este método faz consultas na base de dados utilizando como filtro a expressão passada por parâmetro.

Esta interface define o que é esperado por cada classe repositório, mas se notarmos ela utiliza um tipo genérico como parâmetro para sua implementação. Para refinarmos o seu uso e tornarmos nosso repositório reutilizável e expansível, acredito que devemos criar para cada classe repositório uma interface que implemente o contrato definido por IRepository<T>, mas que defina qual entidade será persistida ali. Tomemos como exemplo a interface do repositório de clientes, conforme código:

IClientRepository

Seu classe repositório deve implementar ICLientRepository e ser igual a seguinte implementação:

ClientRepository

Observem que nossa classe de repositório implementa a interface IClientRepository utilizando a entidade Client como alvo de nossas ações de persistência no banco de dados, e não um tipo de dados genérico, como utilizado na interface IRepository<T>.

Este uso é indicado ao construirmos nossos testes unitários, pois ao implementarmos nossos repositórios fakes já teremos nossos repositórios bem estruturados e prontos para extensão.

Outra dica para a construção de nossos testes unitários é tornar os repositórios parametrizáveis através de nossas classes controllers. Devemos criar uma assinatura de construtor que permita a parametrização do repositório que utilizaremos em nossa implementação, assim como é importante fornecer um construtor que defina um repositório padrão, caso não seja passado nenhum parâmetro para o repositório, podemos fazer isso desta forma:

clientController

Bom, espero que algumas dicas aqui descritas ajudem a implementação de suas aplicações com o Entity Framework 4.1. Bom estudo e continuem programando… Alegre

[]s!

Por
Fernando Henrique Inocêncio Borba Ferreira