Uma aplicação n-tier nada mais é que uma aplicação em camadas, no caso é uma aplicação com n camadas. Esse tipo de aplicação têm inúmeras vantagens, primeiramente porque você tem uma aplicação bem dividida: uma camada para negócio, uma camada para acesso a dados e uma camada de interface com usuário. Você pode ter também uma camada específica para os serviços, com isso a manutenção no sistema se torna bem mais simples, pois você pode realizar alterações na camada de negócio sem interferir no funcionamento da camada de dados ou na de interface com os usuários. Novas implementações ou até mesmo uma troca de banco de dados se torna muito mais simples uma vez que somente alterando a camada de acesso a dados você já teria outro banco funcionando com o restante da sua aplicação.
O que são classes abstratas?
Classes abstratas são classes que somente podem ser herdadas e nunca instanciadas. Essas classes servem como modelos para suas classes derivadas. As classes que derivam da classe abstrata pode sobrescrever os métodos implementados por ela caso seja necessário.
O que são interfaces?
São as interfaces que definem o que deve ser implementado pela classe, ou seja, é a interface que contem as assinaturas dos métodos e propriedades que deverão obrigatoriamente ser implementados pela classe.
Exemplo prático
Vamos iniciar o nosso projeto abrindo o Visual Studio e criando um novo projeto clicando em File -> New -> Project. Veja a Figura 1.
Figura 1. Criando Novo Projeto
Na janela seguinte digite “empty” na caixa de pesquisa, selecione BlankSolution e altere a propriedade Name para SLNTIER ou para nome que preferir, conforme mostra a Figura 2.
Figura 2. Criando a Solution
Se olharmos no Solution Explorer veremos que foi criada uma solução vazia, então agora clique com o botão direito do mouse e escolha Add... e em seguida New Project. Selecione a opção Class Library e dê o nome de DAL (Data Access Layer) ou DAO(Data Acess Object), pois essa será nossa camada de acesso a dados. Veja os passos nas Figuras 3 e 4.
Figura 3. Adicionando um novo projeto
Figura 4. Class Library DAL
Para que o projeto fique com uma estrutura melhor, vamos criar uma pasta no projeto DAL e nomear como Interface. É nessa pasta que colocaremos todas as interfaces da classe Dal. Para isso, clique com o botão direito do mouse sobre o projeto DAL e escolha a opção Add-> New Item -> Folder, como é ilustrado na Figura 5.
Figura 5. Adicionando uma Pasta
Agora clique com o botão direito do mouse sobre a pasta que acabamos de criar e selecione Add -> New Item. Na janela que abrirá escolha a opção Interface e na propriedade Name coloque IBaseCrud. Essa será nossa Interface padrão, ou seja, as demais Interfaces descenderão dela (Figuras 6 e 7).
Figura 6. Adicionando Interface
Figura 7. Interface IBaseCrud
Agora implemente o código conforme a Listagem 1.
Listagem 1. Interface IBaseCrud
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
namespace DAL.Interface
{
public interface IBaseCrud<T>
{
void Add(T pEntity);
void Delete(T pEntity);
void Update(T pEntity);
T Find(Expression<Func<T, bool>> where);
IQueryable<T> GetAll();
IQueryable<T> GetAll(Expression<Func<T, bool>> where);
void SaveChanges(String Tipo);
}
}
Vamos entender o código acima: na primeira linha colocamos <T>, o que significa que nossa classe é genérica, ou seja, qualquer tipo T poderá implementá-la - essa interface contem as assinaturas dos métodos que nossas classes devem ter, nesse caso, por se tratar de uma interface para CRUD temos os métodos padrões Add, Update, Delete e SaveChanges, todos do tipo void. Além desses, temos ainda o método Find e duas assinaturas para o método GetAll, uma que recebe como parâmetro uma expressão lambda e um método sem parâmetros – Find – que retorna um tipo T e os métodos GetAll retornam um IQueryable<T>.
Agora clique sobre o projeto DAL e selecione Add-> New Item. Na janela que irá se abrir selecione a opção Class e altere a propriedade Name para Abstract_Crud, conforme ilustrado nas Figuras 8 e 9.
Figura 8. Adicionando uma Classe
Figura 9. Classe Abstract_Crud
Agora implemente o código conforme a Listagem 2.
Listagem 2. Implementando Abstract_Crud.
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Objects;
using System.Text;
using DAL.Interface;
namespace DAL
{
public abstract class Abstract_Crud<T> : IBaseCrud<T> where T : class
{
TutoriaisEntities _contexto = new TutoriaisEntities();
private DbSet<T> _entidade;
public Abstract_Crud()
{
_contexto.Configuration.LazyLoadingEnabled = true;
_entidade = _contexto.Set<T>();
}
public void Add(T pEntity)
{
_entidade.Add(pEntity);
}
public void Delete(T pEntity)
{
_contexto.Entry<T>(pEntity).State = System.Data.EntityState.Deleted;
}
public void Update(T pEntity)
{
_contexto.Entry<T>(pEntity).State = System.Data.EntityState.Modified;
}
public T Find(Expression<Func<T, bool>> where)
{
return _entidade.Where(where).ToList().FirstOrDefault<T>();
}
public IQueryable<T> GetAll()
{
return _entidade;
}
public IQueryable<T> GetAll(Expression<Func<T, bool>> where)
{
return _entidade.Where(where);
}
public void SaveChanges(String Tipo)
{
_contexto.SaveChanges();
}
}
}
Vamos entender o que foi implementado acima: a classe Abstract_Crud implementa a interface IBasedCrud que recebe um Tipo T, onde esse tipo T é obrigatoriamente uma classe. No construtor da classe setamos nosso contexto para lazyload true, porém, deve se tomar muito cuidado ao ativar o lazyloading em alguns cenários, pois ele é muito bom, mas na maioria das vezes causa problemas de desempenho. Após o construtor implementamos os métodos básicos do CRUD, conforme definimos na Interface. Lembre-se que todos os métodos da Interface devem ser obrigatoriamente implementados.
Temos um banco de dados com uma tabela Funcionário, e precisamos adicionar um Entity data Model ao Projeto DAL, conforme mostram as Figuras 10 a 14.
Figura 10. Adcionando um novo Item
Figura 11. Ado.Net Entity Data Model
Figura 12. Tipo do Modelo
Figura 13. Conexão
Figura 14. Tabelas
Agora vá até a pasta Interface no projeto DAL e clique com o botão direito do mouse e selecione Add-> new Item. Escolha a opção Interface e na Propriedade Name coloque IFuncionarios, conforme a Figura 15.
Figura 15. Interface IFuncionarios
Veja que conforme Listagem 3, a implementação é bem simples: o que temos que fazer é herdar a interface IBaseCrud e passar como parâmetro nossa Entidade FUNCIONARIO que está no nosso Entity data Model. Caso deseje ter outros métodos além dos já criados, você pode colocar as suas assinaturas aqui.
Listagem 3. Entidade FUNCIONARIO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DAL.Interface
{
public interface IFuncionarios : IBaseCrud<FUNCIONARIO>
{
}
}
Adicione uma nova classe ao projeto DAL e altere a propriedade Name para Funcionarios. Nessa classe você deve herdar da Classe Abstract_Crud passando como parâmetro a Entidade FUNCIONARIO. Implemente a Interface IFuncionario conforme a Listagem 4.
Listagem 4. Interface IFuncionario
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL.Interface;
namespace DAL
{
public class Funcionarios : Abstract_Crud<FUNCIONARIO>, IFuncionarios
{
}
}
Devido a nossa classe Funcionarios descender da Abstract_Crud, ela já possui os métodos Add, update Delete Find e GetAll, portanto, só será necessário implementar métodos que você tenha na sua Interface IFuncionarios.
Vamos à implementação da camada de negócio ou BO (Business Object). Para isso, acesse o solution explorer e clique com o botão direito do mouse sobre a nossa solution e selecione Add New Project. Escolha a opção ClassLibrary e altere a propriedade Name para BO, conforme as Figuras 16 e 17.
Figura 16. Adicionando Novo Projeto
Figura 17. Class Library BO
Acesse o arquivo class1 e renomeie para FuncionarioBO. Faça a classe herdar a classe Funcionarios da camada DAL, conforme a Listagem 5. Nessa classe é que devemos implementar toda nossa regra de negócios. Apenas como exemplo, vamos implementar um método count que retornará a quantidade de registros na tabela.
Listagem 5. FuncionarioBO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL;
namespace BO
{
public class FuncionarosBO : Funcionarios
{
public int Count()
{
return this.GetAll().Count();
}
}
}
Agora vamos criar nossa última camada que é a UI (User Interface) ou apenas Interface. Acesse novamente o Solution Explorer, clique sobre a nossa solução com o botão direito do mouse e selecione Add New Project. Agora selecione Windows Forms e altere a propriedade Name para UI e clique em Ok, conforme as Figuras 18 e 19.
Figura 18. Adicionando Projeto
Figura 19. Windows Form Application
Acesse a aba Tools e adicione um Panel. Nele adicione um Label, e no form adicione também um DataGridView. Altere a propriedades dos componentes conforme abaixo:
Propriedade/Objeto |
Panel |
Label |
DataGridView |
Name |
pCima |
lbRegistros |
dgFunc |
DOCK |
TOP |
|
Fill |
Agora dê um duplo clique na barra de menu do form1 para que o Visual Studio vá para o Source e crie o método load para o Form1. Nesse método vamos implementar a chamada a classe BO para que possamos alimentar o Grid com os funcionários que estão na tabela no Banco de Dados. Nesse mesmo método também realizaremos a chamada do método Count, que retorna a quantidade de duncionários da tabela. O código deve ficar como o da Listagem 6.
Listagem 6. Método load
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DAL;
using BO;
namespace UI
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
FuncionarosBO funcBO = new FuncionarosBO();
dgFunc.DataSource = funcBO.GetAll().ToList();
lbRegistros.Text = funcBO.Count().ToString();
}
}
}
Abaixo segue a Figura 20 com o resultado fnal.
Figura 20. Resultado Final
Ficamos por aqui com mais um artigo, espero que tenha sido útil.
Até a próxima.