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.