Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Quando o foco principal é o acesso a dados, a maneira como você se comunica com o banco de dados e o modo como representa esses dados na sua aplicação pode determinar o sucesso, ou o fracasso, do seu projeto.
Nesse assunto temos muitas opções, a começar com a utilização de objetos ADO .NET, como connections, adapters, readers e datasets. Essa abordagem é simples e fácil de ser entendida e permite que você tenha um desenvolvimento bem rápido.
Outra opção é utilizar classes ADO .NET para interagir com o banco de dados e, então, criar suas próprias classes (modelo de objetos) para representar os dados na sua aplicação. A curva inicial com tal modelo é maior, se comparada com a primeira, mas a longo prazo esta abordagem garante uma alta manutenção.
Uma terceira opção a ser considerada é utilizar uma ferramenta ORM, que esconde a complexidade de usar as classes ADO .NET e permite que você trabalhe somente com objetos em sua aplicação. Uma ferramenta ORM inclui o melhor das duas opções citadas acima, porque ela oferece uma produtividade imediata.
Mapeamento do objeto-relacional (ou ORM, do inglês: Object-relational mapping) é uma técnica de desenvolvimento utilizada para reduzir a impedância da programação orientada aos objetos, utilizando bancos de dados relacionais. As tabelas do banco de dados são representadas através de classes e os registros de cada tabela são representados como instâncias das classes correspondentes.
Considerando a plataforma .NET, a Microsoft criou a ferramenta ORM - conhecida como Entity Framework - adotando-a como a melhor prática para o acesso a dados. Dessa forma, vamos considerar apenas o Entity Framework, que atualmente esta na versão 4.1, para utilização em projeto com acesso a dados.
Com isso em mente, temos que compreender que o acesso a dados usando o Entity Framework é de vital importância, pois é partir de sua utilização que iremos nos apoiar para desenvolver nossas aplicações com acesso a dados.
Projetando uma aplicação com acesso a dados Como exemplo, vamos criar uma aplicação que trata os pedidos para o banco de dados Northwind, onde temos dados sobre clientes e produtos armazenados nas tabelas: Orders, Customers, Order Details e Products. Abaixo, uma figura mostra essas tabelas no banco de dados:
/applications/core/interface/imageproxy/imageproxy.php?img=http://conteudo.imasters.com.br/23696/45116.gif&key=5be4f776354ee085060b91d7ce336d7e116f65d7706caa9e98d19d239bd298f2" />
Para começar, precisamos criar o nosso modelo de objetos, que são classes que tratam os dados e que são preenchidas com as informações a partir do banco de dados. Essas classes também precisam tratar os dados que atualizam o banco de dados.
Para o nosso exemplo, vamos criar as classes Order, Customer, Order_Detail e Product que conterão as propriedades que representam os dados no banco de dados e que serão úteis para o negócio. Essas classes escondem a complexidade da estrutura do banco de dados a partir do código de negócio, também conhecido como camada de negócios ou Bussines Logic Layer (BLL), permitindo que o código se comunique somente com elas e com uma camada específica, que será responsável por interagir com o banco de dados (Data Access Layer ou DAL).
A camada de lógica de negócios não sabe nada sobre o banco de dados e interage apenas com as quatro classes. A DAL é responsável por se comunicar com o banco de dados e com isso, as classes que criamos se tornam-se a camada de negócio do banco de dados da camada Lógica.
/applications/core/interface/imageproxy/imageproxy.php?img=http://conteudo.imasters.com.br/23696/45117.gif&key=0147d9103d92a1edb4998e953165522796d79386e51ce6135b61071bb38e09bb" />A BLL usa as classes no modelo e então persiste as modificações via DAL. O código da BLL não sabe se conectar com um banco de dados.
A separação do código dentro de camadas isoladas é uma técnica que garante um desenvolvimento mais rápido e, talvez, mais importante, assim como uma manutenção mais fácil. Até o momento, já dissemos que o modelo contém classes que, por sua vez, contêm dados que são persistido no banco.
Mas como você deve fazer um modelo? Quais as técnicas que você precisa usar para construí-lo? A resposta é: depende.
O que é um modelo de objeto? Em muitas aplicações, um modelo pode ser um simples conjunto de classes que contêm dados provenientes de um banco de dados e que têm pouco comportamento. Este tipo de modelo é conhecido como um modelo de objetos. Vejamos algumas das características das classes do modelo de objetos:
No banco de dados, as tabelas são conectadas pelas colunas-chave estrangeiras. No modelo de objetos podemos referenciar diretamente outra classe usando a propriedade do tipo da classe referenciada. Por exemplo: a classe Order mantém uma referência a classe Customer usando a propriedade Customer (podemos usar o nome do cliente), cujo tipo é Customer.
Se um objeto precisa referenciar múltiplos objetos, você pode criar uma propriedade enumeration do tipo List<T>, onde T é o tipo de objeto na coleção. Por exemplo, um pedido precisa referenciar uma lista de detalhes (itens) e para fazer isso a classe Order contém a propriedade Order_Details, que é do tipo List<Order_Detail> (você não precisa, necessariamente, usar List<T>. Pode lançar mão de outras classes do tipo coleção, como Colletion<T>, HashSet<T> ou mesmo a classe não genérica ArrayList).
Quando você completar o processo de desenhar os relacionamentos do modelo de objetos, você deverá ter algo parecido com o que mostra a figura abaixo:
/applications/core/interface/imageproxy/imageproxy.php?img=http://conteudo.imasters.com.br/23696/45118.gif&key=4521e95136c51e47fb3889ce3b0bc07299d10e3c2784ea33550a37b40a3297cd" />
- A classe Order está ligada à classe Customer pela propriedade Customer;
- A Classe Order também contém detalhes através da propriedade Order_Details;
A evolução do modelo de objetos : o modelo de domínio Um modelo de domínio é um modelo de objetos no qual as classes têm mais comportamentos. O comportamento que é adicionado ao modelo de classes de domínio cria uma integração ampla e rica entre as classes e o meio ambiente.
/applications/core/interface/imageproxy/imageproxy.php?img=http://conteudo.imasters.com.br/23696/45119.gif&key=690b6da242014aa5de42c503e74e32b85028bac2fcf0b6ddade497e4a87fd599" />
O modelo de domínio não envolve apenas as classes e seus dados, ele introduz um novo design para sua aplicação. As classes são integradas à camada de negócios e se comunicam com os módulos do repositório, que são um tipo de porta para o banco de dados. Assim, todas essas classes e módulos tornam-se uma única camada: o modelo de domínio.
O modelo de domínio não se comunica diretamente com o banco de dados. Uma camada de infra-estrutura que oculta a comunicação de dados e que está por baixo do modelo é que faz esse trabalho. Os repositórios lidam com a camada de infra-estrutura que são usadas para enviar os comandos, para recuperar ou atualizar os dados de um banco.
Nota: Como as classes estão cientes dos repositórios, eles podem recuperar dados do banco e assim oferecem uma nova gama de serviços para os desenvolvedores. O padrão de projeto modelo de domínio (Domain Model) contém muitas outras características. Para mais detalhes, consulte o livro de Eric Evans - Domain Driven Design.
Agora você já sabe como definir as camadas de um aplicativo para criar um design melhor e um código mais sustentável. Desenvolver em camadas é fundamental para uma aplicação bem-sucedida e toda essa discussão leva em conta que você tem que lidar com um banco de dados e com objetos cujos dados devem ser persistentes.
Agora, vamos descobrir como você pode fazer isso usando uma ferramenta ORM, como o Entity Framework.
Usando um ORM para construir a camada de acesso a dados Uma ORM é uma framework que lhe permite construir aplicações baseadas em um paradigma que é completamente diferente do que você usa quando você trabalha diretamente com ADO.NET. Usando um ORM você pode apenas trabalhar com objetos e ignorar o banco de dados.
Um ORM permite mapear suas classes e propriedades em tabelas e colunas no banco. Você pode projetar suas classes e tabelas de forma independente e depois deixar o ORM usar as informações de mapeamento para gerar o código SQL para ler os dados a partir de um banco de dados, criar objetos com ela e persistir os dados nos objetos dentro do banco (o código SQL é executado através de ADO.NET, que permanece na camada mais baixa).
Dito desta forma, você pode pensar que um ORM é uma ferramenta que apenas gera código, mas ela faz muito mais do que isso. Um ORM gerencia as alterações feitas nos objetos e garante a integridade de um determinado objeto, suportando muitos ajustes de otimização. Além disso, um ORM lida com as diferenças entre os banco de dados relacionais e o paradigma OOP - que são diferentes em termos de granularidade dos dados.
Antes de dizer-lhe como usar um ORM, vamos examinar os problemas que ele resolve, de modo que você possa entender melhor como uma ferramenta ORM pode tornar a sua vida mais fácil.
1. A incompatibilidade da granularidade dos dados
O número de classes nem sempre vai ser igual ao número de tabelas no banco de dados, causando uma incompatibilidade conhecida como granularidade dos dados.
Geralmente o endereço residencial de um cliente consiste de rua, cidade, cep, país. Com frequência o endereço de entrega para pedidos possui a mesma informação. Quando você define a tabela no banco de dados, você cria colunas com essas informações nas tabela Customers e Orders.
Quando você define o modelo de classes você geralmente cria uma classe AddressInfo, que contém todas as propriedades relacionadas com o endereço e, então, você reutiliza esta classe nas classes Customer e Order. Ao final, você acaba tendo duas tabelas e três classes, conforme a figura abaixo:
/applications/core/interface/imageproxy/imageproxy.php?img=http://conteudo.imasters.com.br/23696/45120.gif&key=c712643e08a292018860d6d7143c95af9fd12ede190373d8e9f112d13fedd846" />
As classes** Order e Customer possuem a propriedade Adress do tipo AddressInfo, que contém a informação do endereço. No banco de dados, as colunas relacionadas com o endereço são repetidas nas tabelas Customers e Orders.
2. A incompatibilidade dos relacionamentos
Outra diferença entre os modelos relacionais e OOP está na forma como eles mantêm os relacionamentos. Pense sobre o relacionamento Order/Customer. Em um banco de dados, você cria uma coluna-chave estrangeira CustomerId na tabela Pedidos (tabela filho), que aponta para a coluna-chave primária CustomerId, da tabela Customers (tabela pai).
No modelo de objetos, você pode referenciar o cliente (Customer) a partir do pedido (Order), usando uma propriedade do tipo Customer (Cliente), por isso, não há necessidade de uma propriedade-chave estrangeira.
Em um banco de dados, as associações são direcionais da tabela filho para a tabela pai. No modelo de objetos, as associações podem ser tanto unidirecionais, como bidirecionais. Você pode ter a propriedade Customer na classe Order, mas também pode ter uma propriedade Orders na classe Customer.
/applications/core/interface/imageproxy/imageproxy.php?img=http://conteudo.imasters.com.br/23696/45121.gif&key=e9cf50e1d4851cfab0c3a158a0c99d25ffac6f3f28e8e81acf45e9c2247db0ba" />
Os Pedidos (Orders) estão relacionados aos seus Clientes (Customers) através de uma chave estrangeira no banco de dados. No modelo OOP utiliza-se um referência ao objeto.
No caso de um relacionamento muitos-para-muitos, as diferenças entre os bancos de dados relacionais e o paradigma OOP tende a crescer. Imagine o relacionamento entre as tabelas Employees e Territories no banco de dados Northwind. Eles não estão relacionados entre si, através de chaves estrangeiras, mas através de uma terceira tabela: EmployeeTerritories.
/applications/core/interface/imageproxy/imageproxy.php?img=http://conteudo.imasters.com.br/23696/45123.gif&key=fbcb8517a5dee562f6be2e418bb128f1902c75d218ffa8aecd35ed9f6527035e" />No modelo de objetos, você deixa as classes referirem-se diretamente entre si, sem recorrer a uma classe intermediária.
3. A incompatibilidade da herança
Suponha que você tenha que tratar em uma aplicação com dois tipos de clientes : pessoa física e jurídica. Você poderia criar uma classe base para todos os clientes e, a seguir, criar uma classe para cliente pessoa física e outra classe para pessoa jurídica e depois fazer com que essas duas classes herdem da classe base.
Nos banco de dados relacionais, o conceito de herança não existe. O que você pode fazer é criar um artefato para simular a herança. Você pode simular a herança no banco de dados utilizando um dos seguintes três métodos:
- Table-Per-Hierarchy (TPH) - onde uma tabela contém os dados de todas as classes na hierarquia de herança e, geralmente, utiliza uma coluna discriminadora para determinar o tipo de objeto que está armazenado;
- Table-Per-Type - (TPT)**** - onde cada classe na hierarquia de herança tem uma tabela e cada tabela adiciona apenas as colunas que são necessárias para o tipo;
4. A incompatibilidade dos tipos de dados
Existe também o problema do tipo de dados. Em um banco, você geralmente tem os tipos de dados varchar, int, datetime e outros tipos de dados que pode ou não ter uma contrapartida na plataforma .NET.
Como exemplo, veja o tipo de dados int do SQL Server. Você pode mapeá-lo para uma propriedade Int32 e ele vai funcionar perfeitamente. Agora, pense sobre o tipo de dados varchar, que pode ser facilmente mapeado para uma string. Mas se a coluna tem um comprimento máximo, você não pode representar o tipo varchar usando o tipo string da plataforma .NET sem ter que escrever um código para verificar o seu tamanho. A situação fica mais complicada para tipos de dados como TimeStamp, que são representados como um array de bytes.
Ao escrever o seu código usando ADO .NET, você tinha que tratar todas essas diferenças. Se você usar uma ferramenta ORM, ela trata essas diferenças para você e você pode se concentrar apenas nos objetos que interagem com o banco de dados.
Vimos, assim, os problemas que um ORM resolve e como isso pode tornar a sua vida mais fácil quando você lidar com aplicações com acesso a dados. Na segunda parte desse artigo veremos como usar a ferramenta ORM Entity Framework.
Carregando comentários...