Você está na página 1de 14

ASP .

NET – Acessando PostGreSQL em


camadas e com padrões de projeto –
Parte 01
PorJosé Carlos Macoratti em 07/10/2010

0 Curtiram

... SHARES

Compartilhe!

Este artigo vai mostrar como criar uma aplicação em


camadas com camada de negócios, interface e camada de acesso a dados para acessar
um banco de dados PostgreSQL usando as boas práticas.

Em meu artigo ASP .NET – Conexão com o


PostGreSQL, eu mostrei como acessar e exibir os dados de uma tabela do PostGreSQL
usando o modo
mais prático, mas não o mais recomendado.

Como eu já
mostrei o que você precisa fazer para poder realizar a conexão com o PostGreSQL,
não vou repetir tudo novamente. Vou focar na construção de uma aplicação
usando as boas práticas e padrões de projeto com ADO .NET.

Para este
artigo, eu criei uma tabela chamada alunos no PostGreSQL com a seguinte
estrutura usando pgAdmin:

Nessa tabela, temos que o campo alunoid é do


tipo serial, ou seja, é equivalente ao campo autonumeração. A chave
primária da tabela também é o campo alunoid.

Nosso objetivo inicial será acessar os dados desta tabela


alunos e exibi-los em um
controle GridView em uma página ASP .NET.

Parece bem simples, mas vamos mostrar como fazer isso criando uma aplicação
onde iremos separar a interface da camada de acesso a dados e criarmos também uma
camada de negócio e de entidades. Acompanhe…

Mesmo para aplicações simples, eu recomendo que você sempre utilize as boas
práticas, e a separação da camada de interface do acesso aos dados é uma delas.
Antes de iniciar, quero deixar claro que esta não é a única forma de você criar uma
aplicação em camadas; você pode simplificar ou refinar o exemplo mostrado neste
artigo de acordo com suas necessidades. Eu já publiquei diversos artigos sobre esse
assunto e se você compará-los verá que, mesmo o assunto sendo o mesmo, ele é tratado
de forma um pouco diferente em cada artigo, isso para que você veja as opções
disponíveis e possa incorporar a que melhor se ajusta ao seu caso.

Vou começar desenhando o cenário:

Nosso banco de dados PostGreSQL está instalado em um servidor web e precisamos


acessar a tabela alunos e exibir os seus dados em uma página ASP .NET usando um
controle GridView.

Temos, então, que criar uma aplicação ASP .NET, que neste artigo irá usar WebForms,
mas poderíamos usar MVC também.

Criando a solução e os projetos

Abra o VS 2008 e, no menu File, selecione New Project.

A seguir, selecione a linguagem Visual C# (poderíamos fazer em VB .NET, mas vou


variar um pouco) e, em Templates, selecione ASP .NET Web Application, informando
o nome EscolaWeb e clicando em OK.

Será criado um projeto Web chamado EscolaWeb, contendo a página Default.aspx , o


arquivo web.config, a pasta App_Data e as pastas Properties e References.

Esse seria o caminho padrão para conseguir o nosso objetivo, bastava agora colocar o
controle na página Default.aspx e no code-behind inserir o código para realizar o acesso
ao banco de dados, obter os dados da tabela e exibir no controle GridView. Isso nós já
fizemos no meu artigo citado no início.

Vamos criar uma aplicação mais robusta em camadas com a seguinte estrutura:

 Camada de Entidades – Entidades – deverá possuir as classes que representam as


entidades do nosso negócio. Para o nosso caso teremos, neste momento, a entidade
Aluno que será representada pela classe Aluno.cs;
 Camada de Negócios – CamadaNegocios – deverá conter as classes para definir as
regras do negócio e validação dessas regras. Para este exemplo, essa camada servirá
como uma ponte que irá acessar a camada de acesso a dados;
 Camada de Acesso a dados – CamadaAcessoDados – deverá conter as classes
responsáveis pelo acesso e persistência de dados no banco de dados;
 Camada de Interface – EscolaWeb – Conterá as páginas ASP.NET para exibição e
entrada de dados do usuário.

Deveremos ter, então, uma solução com 4 projetos, onde o primeiro projeto,
EscolaWeb, já foi criado. Vamos criar os demais…
No menu File selecione Add e a seguir New Project.

Selecione Visual C# -> Windows e na janela Templates o modelo Class Library


informando o nome Entidades e clicando em OK.

Repita o procedimento anterior e crie da mesma forma os projetos CamadaNegocios,


CamadaAcessoDados.

Ao final, a nossa janela Solution Explorer deverá exibir uma solução com 4 projetos
conforme a figura abaixo:

Definindo as referências entre os projetos

Após criar a estrutura da solução, temos que pensar como os projetos irão se relacionar
entre si. Estamos criando camadas em projetos distintos, de forma a separar as
responsabilidades de cada camada e, dessa forma, a camada de apresentação não deverá
saber nada da camada de acesso a dados. Com isso em mente, teremos a seguinte
hierarquia de relacionamento entre os projetos:

EscolaWeb => CamadaNegocios => CamadaAcessoDados => Entidades


Entidades Entidades

Ou seja:

 A camada de interface EscolaWeb deverá ter uma referência a CamadaNegocios e


Entidades;
 A camada de negócios CamadaNegocios deverá ter uma referência para
CamadaAcessoDados e Entidades;
 A camada de acesso a dados CamadaAcessoDados deverá ter uma referência a
Entidades.

Isso pode ser visto clicando com o botão direito do mouse na Solução e selecionando o
item Project Dependencies:

Observe que a camada (projeto) Entidades deverá ser referenciado nos demais projetos.

A seguir, veremos como definir estas referências entre os projetos.

 Selecione o projeto EscolaWeb e clique com o botão direito do mouse selecionando a


opção Add Reference;
 Na janela Add Reference, abra a aba Projects e selecione os projetos que deseja como
referência para esse projeto e clique em OK.
Repita este procedimento para referenciar os demais projetos conforme indicado.

Com a estrutura da solução pronta, e as referências definidas, podemos iniciar a fase de


codificação, e vamos começar pelo projeto Entidades. Nesse projeto, teremos a classe
que representa a entidade Aluno, que fisicamente existe como uma tabela do banco de
dados chamada alunos.

Definindo o código da camada Entidades

Abra o projeto Entidades e renomeie a classe Class1.cs criada por padrão para Aluno.cs
e defina esse arquivo o seguinte código:

using System;
using System.Collections.Generic;
using System.Text;
namespace Macoratti.Entidades
{
public class Aluno
{
public Aluno() { }
public int Alunoid { get; set; }
public int Turmaid { get; set; }
public string Apelido { get; set; }
public string Nome { get; set; }
public string Email { get; set; }
public char Sexo { get; set; }
public Aluno(int alunoid, int turmaid, string apelido, string
nome, string email, char sexo)
{
this.Alunoid = alunoid;
this.Turmaid = turmaid;
this.Apelido = apelido;
this.Nome = nome;
this.Email = email;
this.Sexo = sexo;
}
}
}

A classe Aluno define os membros representando cada campo da tabela alunos e


também um construtor vazio e outro onde definimos os valores para cada membro.

Essa classe servirá como um transporte de dados (DTO-Data Transfer Objects) entre as
camadas, pois, como veremos mais à frente, iremos trabalhar com o objeto Aluno para
obter informações da tabela do banco de dados.

Lembrando que para cada entidade de negócio teremos uma classe que a represente e,
no momento, temos somente a tabela alunos e a entidade Aluno.
Definindo o código da camada de Acesso a dados

Na camada de acesso a dados, devemos ter as classes que realizam o acesso e a


persistência dos dados. A nossa camada de acesso a dados deverá ter a seguinte
estrutura:

 Interface – IAcessoDadosObject – contendo as assinaturas dos métodos para realizar


as operações CRUD no banco de dados;
 A classe DALHelper – contendo os métodos para acessar e persistir dados usando
datareaders, datasets, e os recursos da ADO .NET;
 A classe AlunoDAL – que deverá herdar da interface IAcessoDadosObject – e que
deverá implementar os métodos definidos na interface.

Clique com o botão direito do mouse sobre o projeto CamadaAcessoDados e selecione


Add -> Class e informe o nome IAcessoDadosObject.cs e clique em OK.

A seguir, defina o seguinte código na interface criada:

using System;
using System.Collections.Generic;
namespace Macoratti.DAL
{
public interface IAcessoDadosObject <T> where T : new()
{
T Get<K>(K id);
List<T> GetTop();
void Insert(T obj);
void Update<K>(K id, T obj);
void Delete<K>(K id);
}
}

Essa interface define a assinatura dos métodos para obter e atualizar informações na
tabela alunos usando Generics. Observe que estamos tipando a interface de forma
genérica e os métodos serão usados pelas demais classes.

Temos um contrato para definir os métodos:

 T Get<K>(K id); -> retorna um único aluno pelo id informado;


 List<T> GetTop(); – retorna uma lista de alunos;
 void Insert(T obj); – inclui um aluno;
 void Update<K>(K id, T obj); atualiza um aluno;
 void Delete<K>(K id); exclui um aluno.

A classe DALHelper poderá conter os métodos que você achar necessário para acessar
tabelas e banco de dados e tratar conexões.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using Npgsql;

namespace Macoratti.DAL
{
public class DALHelper
{
string server = "localhost";
string port = "5432";
string database = "macoratti";
string userId = "macoratti";
string userPassword = "numsey";
public NpgsqlConnection conexaoBD { get; set; }
public string stringConexaoBD { get; set; }
public DALHelper()
{
this.stringConexaoBD =
string.Format("Server={0};Port={1};Database={2};User
Id={3};Password={4};",

server, port, database, userId, userPassword);


this.conexaoBD = new
NpgsqlConnection(this.stringConexaoBD);
}
public DALHelper(string stringConexaoBD)
{
this.conexaoBD = new
NpgsqlConnection(this.stringConexaoBD);
}
public static DALHelper Create()
{
return new DALHelper();
}
public static DALHelper Create(string stringConexaoBD)
{
return new DALHelper(stringConexaoBD);
}
public void OpenConnection()
{
if (this.conexaoBD.State ==
System.Data.ConnectionState.Closed)
{
this.conexaoBD.Open();
}
}
public void CloseConection()
{
this.conexaoBD.Close();
}
public NpgsqlDataReader ExecuteDataReader(string sql)
{
NpgsqlDataReader dr = null;
try
{
if (this.conexaoBD.State ==
System.Data.ConnectionState.Closed)
{
this.conexaoBD.Open();
}
NpgsqlCommand cmd = new
NpgsqlCommand(sql,this.conexaoBD);
dr = cmd.ExecuteReader();
return dr;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
}

A classe DALHelper é uma classe que nos auxilia a realizar consultas e operações
CRUD na base de dados. Ele possui a definição da variáveis usadas na conexão com o
banco de dados e os métodos:

 Construtores DALHelper – criam e retornam uma conexão com base em uma string de
conexão padrão ou fornecida;
 OpenConnection – abre uma conexão;
 CloseConnection – fecha uma conexão;
 ExecuteDataReader – retorna um datareader.

Observe que essa classe usa os namespaces System.Data e NpgSql, que dá acesso as
classes ADO .NET e ao conector Npgsql, que dá acesso às classes dos provedores para
acesso ao banco de dados PostgreSql (Lembre-se que você tem que referenciar a library
do conector Npgsql nesse projeto).

Falta definir a classe AlunosDAL, que deverá implementar os métodos definidos na


interface. Essa classe deverá implementar a interface que foi definida.

Como para esse momento eu vou precisar somente acessar os dados da tabela, somente
vou definir o código completo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Npgsql;
using Macoratti.Entidades;
namespace Macoratti.DAL
{
public class AlunoDAL : IAcessoDadosObject<Aluno>
{
private DALHelper dal = new DALHelper();
public Aluno Get<K>(K id)
{
throw new NotImplementedException();
}
public List<Aluno> GetTop()
{
List<Aluno> alunos = new List<Aluno>();
NpgsqlDataReader reader = null;
try
{
string query = "select * from alunos";
dal.OpenConnection();
reader = dal.ExecuteDataReader(query);
while (reader.Read())
{
Aluno aluno = new Aluno();
aluno.Turmaid =
Convert.ToInt32(reader["turmaid"]);
aluno.Apelido = reader["apelido"].ToString();
aluno.Email = reader["email"].ToString();
aluno.Nome = reader["nome"].ToString();
aluno.Sexo = Convert.ToChar(reader["sexo"]);
alunos.Add(aluno);
}
reader.Close();
}
finally
{
if (reader != null)
{
reader.Close();
}
this.dal.CloseConection();
}
return alunos;
}
public void Insert(Aluno oAluno)
{
throw new NotImplementedException();
}
public void Update<K>(K id, Aluno oAluno)
{
throw new NotImplementedException();
}
public void Delete<K>(K id)
{
throw new NotImplementedException();
}
}
}

Nessa classe, temos a implementação dos métodos declarados na interface


IAcessoDadosObject, sendo que a classe recebe o tipo Aluno e o método GetTop()
retorna uma lista de objetos alunos.

Obs: Na verdade, o único método completamente implementado é o método


ExecuteDataReader, os outros irei implementar conforme for precisando.

O método GetTop() utiliza uma chamada ao método ExecuteDataReader da classe


DALHelper, passando como parâmetro a consulta SQL.

Na continuação deste artigo irei definir a camada de Negócios, onde estarei usando o
padrão Factory e Facade para, em seguida, poder exibir os dados na camada de
interface. Aguarde a continuação do artigo!

Eu sei é apenas, ASP .NET com boas práticas e padrões de projeto, mas eu gosto…
ASP .NET – Acessando PostGreSQL em
camadas e com padrões de projeto –
Parte 02
PorJosé Carlos Macoratti em 21/10/2010

0 Curtiram

... SHARES

Compartilhe!

Na primeira parte deste artigo, vimos como criar uma aplicação em


camadas com camada de negócios, interface e camada de acesso a dados para acessar
um banco de dados PostgreSQL usando as boas práticas.

Nesta segunda parte, vamos definir as classes da


camada de negócios através das quais iremos acessar a camada de acesso a dados –
DAL, criada na primeira parte do artigo.

Lembrando que a camada de negócios já foi criada


como um projeto do tipo Class Library e que tem como referência o projeto
CamdaAcessoDados e o projeto Entidades conforme exibe a figura
abaixo obtida no Project Dependencies:

Na verdade, em vez de criar as camadas como projetos, eu poderia ter criado


uma hierarquia de pastas na solução e ter realizado uma separação lógica entre
as camadas; a vantagem de criar um projeto é que podemos distribuir a dll dele para
referenciar outros projetos. Mas essa decisão depende da
complexidade do projeto que estamos tratando.

A camada de negócios geralmente contém as regras do negócio e as validações


das solicitações antes de serem repassadas para a camada de acesso a dados.
Quando eu digo regra de negócio, eu me refiro a regras específicas, pertinentes à
sua aplicação, como um cálculo complexo ou uma rotina que realiza uma operação que
só o seu negócio tem e que o diferencia dos demais, além, é claro das regras
gerais pertinentes a qualquer negócio como cálculo de impostos, alíquotas, etc.

Como nossa aplicação é muito incipiente e no momento o objetivo é apenas


acessar os dados de uma tabela do banco de dados e exibi-los em uma página
ASP .NET, não teremos que nos preocupar com regras de negócio, apenas vamos
criar a estrutura que poderá ser usada para atingir o nosso objetivo e, no futuro,
implementar tais regras quando elas se fizerem necessárias.
Aqui eu vou mostrar na figura abaixo (que eu adaptei de uma figura
encontrada) um esquema do que seria a arquitetura da nossa solução:

Nessa figura, eu estou exibindo a


arquitetura da nossa solução e detalhando a camada de negócios onde temos:

 A classe FactoryDAO.cs que usa o padrão Factory e serve para


criar instâncias das classes;
 A classe Facade.cs que usa o padrão Facade e permite agrupar em
uma única classe as chamadas aos métodos que iremos usar;
 A classe AlunoFacade.cs onde efetivamente chamamos os métodos
que vamos usar para acessar a camada de acesso a dados.

Obs: Tanto a classe Facade.cs como AlunoFacade.cs são


implementadas usando a palavra-chave partial, de forma que temos arquivos
distintos mas que na verdade constituem um único arquivo.

Vejamos então o código de cada uma dessas classes.

O arquivo FactoryDAO.cs:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Macoratti.DAL;

namespace Macoratti.BLL

public static class FactoryDAO

public static AlunoDAL CreateAlunoDAL()

return new AlunoDAL();

}
O padrão Factory fornece uma interface para a
criação de famílias de objetos correlatos ou dependentes sem a necessidade de
especificar a classe concreta desses objetos.

A classe FactoryDAO, como o nome sugere, é uma fabrica de instâncias


para as classes concretas da camada de acesso a dados. No momento, temos somente
a classe AlunoDAL(), mas poderíamos ter muitas outras classes.

O arquivo Facade.cs:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Macoratti.DAL;

namespace Macoratti.BLL

public partial class Facade

private AlunoDAL _alunoDAL;

public Facade()

_alunoDAL = FactoryDAO.CreateAlunoDAL();

A classe Facade usa o padrão do mesmo nome para agrupar as chamadas


que serão feitas a camada de acesso a dados via camada de negócios.

Em padrões
de projeto, um façade (fachada, em francês) é um objeto que
disponibiliza uma interface para uma grande quantidade de funcionalidades de
uma API, por exemplo. Um façade pode:

 tornar uma biblioteca de software mais fácil de


entender e de usar;
 tornar o código que utiliza essa biblioteca mais fácil
de entender;
 reduzir as dependências em relação às características
internas de uma biblioteca, trazendo flexibilidade no desenvolvimento do
sistema;
 envolver uma interface mal desenhada, com uma interface
melhor definida.

O arquivo AlunoFacade.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Macoratti.DAL;
using Macoratti.Entidades;
namespace Macoratti.BLL
{
public partial class Facade
{
public void InserirAluno(Aluno aluno)
{
this._alunoDAL.Insert(aluno);
}

public void UpdateAluno(int id, Aluno aluno)


{
this._alunoDAL.Update<int>(id, aluno);
}
public Aluno GetAluno(int id)
{
return this._alunoDAL.Get<int>(id);
}
public List<Aluno> GetTopAluno()
{
return this._alunoDAL.GetTop();
}
public void DeleteAluno(int id)
{
this._alunoDAL.Delete<int>(id);
}
}
}

Usando o conceito de partial class, você


pode dividir a definição de sua classe em mais de um arquivo físico.

O arquivo AlunoFacade.cs na verdade representa a mesma classe


Facade. A separação é possível pelo uso da palavra-chave partial.
Embora tenhamos definidos os métodos para inserir, atualizar, excluir e obter um
aluno, somente o método GetTopAluno() será usado para obter as informações
da tabela alunos a partir do método GetTop() da camada de acesso a dados.

Agora já temos tudo pronto, só falta definir a camada de interface…


Criando a camada de interface

A camada de interface com o usuário será uma aplicação ASP .NET e estará no
projeto EscolaWeb representado pelo arquivo Default.aspx.

Abra o arquivo Default.aspx e inclua um controle GridView. A


seguir, defina o seguinte código no code-behind Default.aspx.cs:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using Macoratti.BLL;

using Macoratti.Entidades;

namespace Escolaweb

public partial class _Default : System.Web.UI.Page

//cria a instância da classe Facade

Facade _alunoFacade = new Facade();

protected void Page_Load(object sender, EventArgs e)

//usa o método GetTopAluno() da camada de negócios para


acessar a tabela alunos

//e retornar as informações como uma lista de objetos

//exibindo-os no GridView

GridView1.DataSource =
_alunoFacade.GetTopAluno().ToList();

GridView1.DataBind();

}
No código acima, criamos uma instância da classe Facade e em seguida, no
evento Load da página web, chamamos o método GetTopAluno(), definido
na camada de negócios; esse método, por sua vez, chama o método GetTop() da
camada de acesso a dados, que retorna uma lista de objetos alunos.

Abaixo temos um esquema que mostra a hierarquia de chamadas realizadas entre


as camadas:

Antes de executar o projeto, não se esqueça de definir o projeto EscolaWeb como Set
As Startup
Project e a página Default.aspx como Set As Startup Page.

Feito isso, basta rodar a solução que iremos obter o seguinte resultado:

Pegue o projeto completo aqui:


EscolawebPostgreSQL.zip

Eu sei, é apenas ASP .NET com boas práticas


e padrões de projeto,
mas eu gosto…