.NET - Passando dados entre camadas : Usando uma coleção/lista Genérica (List(Of T)/Collection(Of T)
Você já deve saber que usar uma arquitetura em camadas é uma boa prática que deve ser seguida. |
Quando você divide sua aplicação em camadas esta separando as responsabilidades de forma que a camada de apresentação(UI) seja responsável apenas pela interação com o usuário, a camada de negócios(BLL) pelas regras de negócios e a camada de acesso a dados(DAL) apenas pelo acesso e persistência dos dados.
Nota:
|
Então o fluxo da informação nesta abordagem pode ser visto na figura abaixo:
Agora vamos pensar em termos práticos. Se você precisa exibir em um formulário as informações do cliente tem que chamar a camada de negócios (BLL) que por sua vez chama a camada de acesso a dados (DAL).
Se você procurar na internet verá muitos exemplos onde a camada de acesso a dados retorna um objeto DataTable ou DataReader que será usado na camada de apresentação. Mas essa prática não é recomendada. É melhor usar uma coleção genérica do tipo Collection(Of T)/Collection<T>.
Então a extração dos dados é feita na camada de acesso a dados e depois é feita a conversão do DataTable/DataReader obtido para uma coleção genérica. Essa conversão pode ser feita ou na camada de negócios ou na camada de acesso a dados.
A prática mais indicada é definir uma entidade que representa os dados que serão retornados definido em uma camada de transferência que seja referenciada por todas as demais camadas. Essa camada pode ter muitos nomes mas o mais conhecido é DTO ou Data Transfer Object.
Com a definição das entidades podemos realizar o acesso aos dados e converter o resultado de DataTable/DataReader para uma Collection(Of T)/Collection<T> onde T é um tipo da nossa entidade.
Nota: Em muitos exemplos vemos a utilização de List(Of T)/List<T> mas nesse link vemos uma recomendação de não usá-las.
List<T> não é projetado para ser estendido. ou seja, você não pode substituir todos os membros.
Isso significa que um objeto ao retornar List<T> de uma propriedade não será capaz de ser notificado quando a coleção for modificada. Já Collection<T> permite substituir o membro protegido SetItem de forma a ser "notificado" quando um novo item for adicionado ou um item existente for alterado. List<T> tem muitos membros que não são relevantes em muitos cenários. Dizemos que List<T> é muito "ocupado" para modelos de objetos públicos. |
Visual Studio 2012 Express for desktop - Exemplo Prático
Vou dar um exemplo prático procurando ser bem objetivo.
Objetivo: Exibir as informações dos clientes existente em uma tabela Clientes de um banco de dados SQL Server chamado Cadastro.mdf em um controle DataGridView de um formulário Windows Forms.
A estrutura da tabela Clientes e seus dados são vistos abaixo:
Neste exemplo eu vou criar as camadas bem enxutas; nelas eu só vou definir as funcionalidades que precisaremos para ilustrar o exemplo.
Então nosso projeto terá as seguintes camadas :
Teremos assim uma solução com 4 projetos.
Criando a solução e os projetos
Abra o Visual Studio 2012 Express for desktop e clique em New Project e selecione Visual Studio Solutions ->Blank Solution informando o nome PassandoDadosEntreCamadas e clique em OK;
Isso irá criar uma solução vazia , sem projetos. Vamos agora criar os projetos.
1- Criando a camada de apresentação - O projeto Windows Forms
No menu FILE clique em Add -> New Project;
Selecione o template Visual Basic -> Windows Forms e informe o nome CamadaApresentacao.
No formulário form1.vb inclua um controle DataGridView (name=dgvClientes) e 3 Buttons conforme a leiaute da figura abaixo:
Definindo as referências da camada
Clique com o botão direito do mouse sobre o projeto CamadaApresentação e clique em Add Reference;
Na janela Add Reference clique em Projects e marque as referências a CamadaDeNegocios e CamadaDeTransferencia conforme figura abaixo:
2- Criando a camada de transferência - A classe Cliente
No menu FILE clique em Add -> New Project;
Selecione o template Visual Basic ->Class Library e informe o nome Cliente.vb.
A seguir inclua o código abaixo na classe Cliente:
Public Class Cliente Public Property Id As Integer Public Property Nome As String Public Property Endereco As String Public Property Telefone As String Public Property Email As String End Class |
public
class Cliente { public int Id { get; set; } public string Nome { get; set; } public string Endereco { get; set; } public string Telefone { get; set; } public string Email { get; set; } } |
Se você observar a estrutura da tabela Clientes verá que existe uma correspondência entre as propriedades da classe Cliente e os campos da tabela.
Definindo as referências da camada
Esta camada não possui referência a nenhuma camada mas é referenciada por todas.
3- Criando a camada de Acesso aos Dados- A classe ClienteDAL
No menu FILE clique em Add -> New Project;
Selecione o template Visual Basic ->Class Library e informe o nome ClienteDAL.vb.
A seguir vamos definir os dois métodos que acessam a tabela Clientes e retornam uma lista de objetos Cliente.
Os métodos são :
Eu optei por criar um método retornando um List(Of T) mesmo não sendo recomendado para efeito de comparação com Collection(Of T). Como vocês poderão notar quase não há diferenças. A principal diferença é que para usar a classe Collection(Of T) temos que declarar o namespace Imports System.Collections.ObjectModel.
Abaixo vemos o código da classe ClienteDAL:
Imports System.Data Imports System.Data.SqlClient Imports System.Collections.ObjectModel Imports CamadaDeTransferencia Public Class ClienteDAL Private connStr As String = Nothing Sub New() connStr = "Data Source=.\sqlexpress;Initial Catalog=Cadastro;Integrated Security=True" End Sub Public Function CarregaDadosDataReader() As List(Of Cliente) Dim lista = New List(Of Cliente)() Using conn As New SqlConnection(connStr) Using cmd As New SqlCommand("Select * from Clientes", conn) cmd.CommandType = CommandType.Text conn.Open() Using reader As SqlDataReader = cmd.ExecuteReader() While reader.Read() Dim p As New Cliente() With { _ .Id = reader.GetInt32(reader.GetOrdinal("id")), _ .Nome = reader.GetString(reader.GetOrdinal("nome")), _ .Endereco = reader.GetString(reader.GetOrdinal("endereco")), _ .Telefone = reader.GetString(reader.GetOrdinal("telefone")), _ .Email = reader.GetString(reader.GetOrdinal("email")) _ } lista.Add(p) End While End Using conn.Close() End Using Return lista End Using End Function Public Function CarregaDadosDataTable() As Collection(Of Cliente) Dim colecao = New Collection(Of Cliente)() Using conn As New SqlConnection(connStr) Using cmd As New SqlCommand("Select * from Clientes", conn) cmd.CommandType = CommandType.Text Using ad As New SqlDataAdapter(cmd) Dim table As New DataTable() 'abre a conexao conn.Open() ad.Fill(table) conn.Close() ' percorre todas as linhas For Each row As DataRow In table.Rows Dim p As New Cliente() With { _ .Id = Integer.Parse(row("id").ToString()), _ .Nome = row("nome").ToString(), _ .Endereco = row("endereco").ToString(), _ .Telefone = row("telefone").ToString(), _ .Email = row("email").ToString() _ } colecao.Add(p) Next End Using End Using Return colecao End Using End Function End Class |
VB .NET |
using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Collections.ObjectModel; using CamadaTransferencia; public class ClienteDAL { private string connStr = null; public ClienteDAL() { connStr = "Data Source=.\\sqlexpress;Initial Catalog=Cadastro;Integrated Security=True"; } public List<Cliente> CarregaDadosDataReader() { var lista = new List<Cliente>(); using (SqlConnection conn = new SqlConnection(connStr)) { using (SqlCommand cmd = new SqlCommand("Select * from Clientes", conn)) { cmd.CommandType = CommandType.Text; conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { Cliente p = new Cliente { Id = reader.GetInt32(reader.GetOrdinal("id")), Nome = reader.GetString(reader.GetOrdinal("nome")), Endereco = reader.GetString(reader.GetOrdinal("endereco")), Telefone = reader.GetString(reader.GetOrdinal("telefone")), Email = reader.GetString(reader.GetOrdinal("email")) }; lista.Add(p); } } conn.Close(); } return lista; } } public Collection<Cliente> CarregaDadosDataTable() { var colecao = new Collection<Cliente>(); using (SqlConnection conn = new SqlConnection(connStr)) { using (SqlCommand cmd = new SqlCommand("Select * from Clientes", conn)) { cmd.CommandType = CommandType.Text; using (SqlDataAdapter ad = new SqlDataAdapter(cmd)) { DataTable table = new DataTable(); //abre a conexao conn.Open(); ad.Fill(table); //fecha a conexão conn.Close(); // percorre todas as linhas foreach (DataRow row in table.Rows) { Cliente p = new Cliente { Id = int.Parse(row["id"].ToString()), Nome = row["nome"].ToString(), Endereco = row["endereco"].ToString(), Telefone = row["telefone"].ToString(), Email = row["email"].ToString() }; colecao.Add(p); } } } return colecao; } } } |
C# |
Definindo as referências da camada
Clique com o botão direito do mouse sobre o projeto CamadaAcessoDados e clique em Add Reference;
Na janela Add Reference clique em Projects e marque a referência a CamadaDeTransferencia conforme figura abaixo:
4 - Criando a camada de Negócios- A classe ClienteBLL
No menu FILE clique em Add -> New Project;
Selecione o template Visual Basic ->Class Library e informe o nome ClienteBLL.vb.
A classe ClienteBLL é responsável pela lógica de negócio e validações. No nosso exemplo criaremos dois métodos que acesso os métodos definidos na camada de acesso a dados:
A seguir temos o código da classe ClienteBLL:
Imports CamadaAcessoDados Imports CamadaDeTransferencia Imports System.Collections.ObjectModel Public Class ClienteBLL Public Function CarregaDadosdoDataReader() As List(Of Cliente) Return New ClienteDAL().CarregaDadosDataReader() End Function Public Function CarregaDadosdoDataTable() As Collection(Of Cliente) Return New ClienteDAL().CarregaDadosDataTable() End Function End Class |
using System.Collections.Generic; using System.Collections.ObjectModel; using CamadaTransferencia; namespace CamadaDeNegocios { public class ClienteBLL { public List<Cliente> CarregaDadosdoDataReader() { return new ClienteDAL().CarregaDadosDataReader(); } public Collection<Cliente> CarregaDadosdoDataTable() { return new ClienteDAL().CarregaDadosDataTable(); } } } |
Definindo as referências da camada
Clique com o botão direito do mouse sobre o projeto CamadaDeNegocios e clique em Add Reference;
Na janela Add Reference clique em Projects e marque as referências a CamadaAcessoDados e CamadaDeTransferencia conforme figura abaixo:
Observe em cada classe de cada camada estamos declarando os namespaces com referências a outras camadas. Para que isso funcione temos que definir as referências entre os projetos.
Você pode visualizar as referências para cada projeto clicando com o botão direito do mouse sobre a solução e clicar a seguir em Properties;
Na janela a seguir clique em Project Dependencies e selecione o projeto na guia Projects para visualizar a respectiva referência:
Definindo o código da Camada de Apresentação
Na camada de apresentação vamos definir o código no evento Click de cada botão de comando conforme mostrado a seguir:
Imports CamadaDeNegocios Imports CamadaDeTransferencia Public Class Form1 Private Sub btnSair_Click(sender As Object, e As EventArgs) Handles btnSair.Click Me.Close() End Sub Private Sub btnCarregaDadosDataReader_Click(sender As Object, e As EventArgs) Handles btnCarregaDadosDataReader.Click dgvClientes.DataSource = New ClienteBLL().CarregaDadosdoDataReader End Sub Private Sub btnCarregaDadosDataTable_Click(sender As Object, e As EventArgs) Handles btnCarregaDadosDataTable.Click dgvClientes.DataSource = New ClienteBLL().CarregaDadosdoDataTable End Sub End Class |
using System; using System.Windows.Forms; using CamadaDeNegocios; namespace CamadaApresentacao { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void btnDataReader_Click(object sender, EventArgs e) { dgvClientes.DataSource = new ClienteBLL().CarregaDadosdoDataReader(); } private void btnDataTable_Click(object sender, EventArgs e) { dgvClientes.DataSource = new ClienteBLL().CarregaDadosdoDataTable(); } } } |
Em cada botão estamos criando uma instância da classe ClienteBLL e chamando o respectivo método que retornará a lista/coleção de objetos Cliente que serão exibidos no controle DataGridView dgvClientes através da propriedade DataSource.
O Resultado da execução do projeto é visto a abaixo:
Pegue o projeto completo
aqui: PassandoDadosEntreCamadasVBNET.zip (VS 2012) e
PassandoDadosEntreCamadasCSharp.zip (VB 2010)
João 8:34
Replicou-lhes Jesus: Em verdade, em verdade vos digo que todo aquele que comete pecado é escravo do pecado.João 8:35
Ora, o escravo não fica para sempre na casa; o filho fica para sempre.João 8:36
Se, pois, o Filho vos libertar, verdadeiramente sereis livres.
Veja os
Destaques e novidades do
SUPER DVD Visual Basic (sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ? Veja mais sistemas completos para a plataforma .NET no Super DVD .NET , confira... Quer aprender C# ?? Chegou o Super DVD C# com exclusivo material de suporte e vídeo aulas com curso básico sobre C#. Veja também os Cursos com vídeo aulas e projetos exemplos: |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências: