Na primeira parte deste artigo apresentei os conceitos sobre uma aplicação em 3 camadas e criei a solução definindo sua arquitetura e estrutura no Visual Studio Express 2012 for web.
Vamos continuar definindo as funcionalidades de cada camada iniciando pela camada de acesso a dados : DAL.
Recursos usados:
Como o assunto do artigo já foi exaustivamente abordado em meu site não vou me ater muito a certos detalhes para tornar o artigo mais simples e objetivo possível para aqueles que estão tendo o seu primeiro contato com um projeto em 3 camadas.
Definindo as funcionalidades da DAL
A camada de acesso a dados é responsável pelo acesso e persistência de informações no banco de dados usado pela aplicação.
No nosso exemplo vamos utilizar o SQL Server 2012 Local DB onde teremos um banco de dados Cadastro.mdf e uma tabela Clientes com a seguinte estrutura:
O banco de dados e a tabela podem ser criados no próprio ambiente do Visual Studio através da janela DataBase Explorer.
A string de conexão com o banco de dados para o nosso exemplo é definida como : "Data Source=(LocalDB)\v11.0;Initial Catalog=Cadastro;Integrated Security=True"
E vamos armazena-la no arquivo de configuração da aplicação Web.Config criando uma seção <connectionString> conforme abaixo:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<connectionStrings>
<add name="conexaoClienteSQLServer" connectionString="Data Source=(LocalDB)\v11.0;Initial Catalog=Cadastro;Integrated Security=True"/>
</connectionStrings>
</configuration>
|
Note que identificamos a string de conexão pela tag <add name> com o nome : conexaoClienteSQLServer
Para poder acessar e obter o valor da string de conexão no arquivo Web.Config temos que incluir uma referência ao namespace System.Configuration no projeto DAL.
Clique com o botão direito sobre o projeto DAL e selecione Add Reference;
Na janela Add Reference clique em Assemblies e selecione o item System.Configuration clicando no botão OK:
Portanto as ações para acessar, incluir, alterar e excluir dados deverá ser feita exclusivamente pela camada de acesso a dado a dados.
Para isso vamos criar uma classe no projeto DAL chamada AcessoDB.vb
Esta classe deverá ter somente referências a classes para acesso a dados e não deverá conter nenhuma referência a outras classes.
Digite o código abaixo no arquivo AcessoDB.vb :
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration
Imports DTO
Public Class AcessoDB
Private Shared Function GetDbConnection() As SqlConnection
Try
Dim conString As String = ConfigurationManager.ConnectionStrings("conexaoClienteSQLServer").ConnectionString
Dim connection As SqlConnection = New SqlConnection(conString)
connection.Open()
Return connection
Catch ex As Exception
Throw ex
End Try
End Function
Public Shared Function ExecuteReader(ByVal sql As String) As IDataReader
Dim reader As IDataReader = Nothing
Using connection As SqlConnection = GetDbConnection()
Try
Using command As New SqlCommand(sql, connection)
reader = command.ExecuteReader()
End Using
Catch ex As Exception
Throw
End Try
Return reader
End Using
End Function
Public Function ExecuteNonQuery(ByVal sql As String) As Integer
Dim i As Integer = -1
Using connection As SqlConnection = GetDbConnection()
Try
Using command As New SqlCommand(sql, connection)
i = command.ExecuteNonQuery()
End Using
Catch ex As Exception
Throw
End Try
Return i
End Using
End Function
Public Shared Function ExecuteDataSet(ByVal sql As String) As DataSet
Dim ds As DataSet = Nothing
Using connection As SqlConnection = GetDbConnection()
Try
Using Command As New SqlCommand(sql, connection)
ds = ExecuteDataSet()
End Using
Catch ex As Exception
Throw
End Try
Return ds
End Using
End Function
Public Shared Function ExecuteDataSet() As DataSet
Dim da As SqlDataAdapter = Nothing
Dim cmd As IDbCommand = New SqlCommand()
Dim ds As DataSet = Nothing
Try
da = New SqlDataAdapter()
da.SelectCommand = CType(cmd, SqlCommand)
ds = New DataSet()
da.Fill(ds)
Catch ex As Exception
Throw
End Try
Return ds
End Function
Public Overloads Shared Function GetDataTable(ByVal sql As String, ByVal parameterNames() As String, ByVal parameterVals() As String) As DataTable
Using connection As SqlConnection = GetDbConnection()
Using da As SqlDataAdapter = New SqlDataAdapter(sql, connection)
Dim table As New DataTable
FillParameters(da.SelectCommand, parameterNames, parameterVals)
da.Fill(table)
Return table
End Using
End Using
End Function
Public Overloads Shared Function GetDataTable(ByVal sql As String) As DataTable
Using connection As SqlConnection = GetDbConnection()
Using da As New SqlDataAdapter(sql, connection)
Dim table As New DataTable
da.Fill(table)
Return table
End Using
End Using
End Function
Public Shared Function SelectScalar(ByVal sql As String, ByVal parameterNames() As String, ByVal parameterVals() As String) As String
Using connection As SqlConnection = GetDbConnection()
Using command As SqlCommand = New SqlCommand(sql, connection)
FillParameters(command, parameterNames, parameterVals)
Return CStr(command.ExecuteScalar)
End Using
End Using
End Function
Public Shared Function SelectScalar(ByVal sql As String) As String
Using connection As SqlConnection = GetDbConnection()
Using command As New SqlCommand(sql, connection)
Return CStr(command.ExecuteScalar)
End Using
End Using
End Function
Public Shared Function CRUD(ByVal sql As String, ByVal parameterNames() As String, ByVal parameterVals() As String) As Integer
Try
Using connection As SqlConnection = GetDbConnection()
Using command As New SqlCommand(sql, connection)
FillParameters(command, parameterNames, parameterVals)
Return command.ExecuteNonQuery()
End Using
End Using
Catch ex As Exception
Throw ex
End Try
End Function
Private Shared Sub FillParameters(ByVal command As SqlCommand, ByVal parameterNames As String(), ByVal parameterVals As String())
Try
If parameterNames IsNot Nothing Then
For i = 0 To parameterNames.Length - 1
command.Parameters.AddWithValue(parameterNames(i), parameterVals(i))
Next
End If
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
|
A classe AcessoDB possui diversos métodos que acessam, retornam e persistem informações em um banco de dados SQL Server. É uma classe bem básica que usa os recursos da ADO .NET.
A maioria dos métodos usa o modificador Shared indicando que o método é estático e que portanto não é um método de instância, dessa forma não precisamos criar uma instância da classe AcessoDB para ter acesso aos métodos basta informar o nome da classe seguida de ponto e o nome do método: AcessoDB.GetDataTable().
Você pode criar uma DAL que ao invés de retornar objetos DataTable, DataSet, DataReader, etc., retorne objetos de negócio usando os recursos do Generics da plataforma .NET.
O conteúdo da classe que faz o papel da DAL pode variar dependendo do cenário de sua aplicação. Como a classe esta em uma camada separada das demais qualquer alteração feita nesta classe não deve alterar as classes das outras camadas.
Essa classe será chamada e referenciada pela camada de negócios(BLL) para realizar quaisquer operações com o banco de dados.
Definindo as funcionalidades da Camada de Negócios - BLL
Na camada de negócios - BLL - iremos ter as classes que tratam as regras de negócio da aplicação. Vamos criar uma interface ICliente.vb onde iremos definir os contratos que deverão ser implementados pela classe ClienteBLL que será a classe que irá realizar o tratamento das regras de negócio da aplicação.
No menu PROJECT clique em Add Class e selecione o template Interface informando o nome ICliente.vb e clicando no botão Add:
Uma interface, no paradigma da orientação a objetos, é um tipo de classe que contém apenas as assinaturas de métodos, propriedades, eventos e indexadores.
A implementação dos membros é feita por uma classe concreta ou struct que implementa a interface.
Nome de uma interface geralmente possui a primeira letra I maiúscula seguido do nome da interface. No nosso caso : ICliente
Digite o código a seguir na interface ICliente:
Imports DTO Public Interface ICliente(Of T)
Function ExibirTodos() As DataTable |
Nesta interface temos a referência ao namespace DTO onde definimos a classe Cliente.
A interface declara métodos contendo apenas a assinatura que deverão se implementados por uma classe concreta.
Nossa interface é uma lista genérica do tipo T onde T representa uma classe que nosso exemplo será a classe Cliente.
O método Exibir() retorna uma lista genérica do tipo T, o método GetClienteId() retorna um tipo Cliente e os métodos Incluir(), Alterar() e Excluir() recebem como argumento um objeto do tipo T.
Para implementar essa interface vamos criar a classe ClienteBLL via menu PROJECT clicando em Add Class e selecionando o template Class.
Na linguagem VB .NET a sintaxe usada para indicar a utilização de uma interface usa a palavra chave Implements após o nome da classe concreta que vai implementar a interface seguido do nome da interface.
Abaixo temos o código da classe concreta ClienteBLL que implementa a interface ICliente:
Imports DAL
Imports DTO
Public Class ClienteBLL
Implements ICliente(Of Cliente)
Public Function GetClienteId(id As Integer) As Cliente Implements ICliente(Of Cliente).GetClienteId
Try
Dim sql As String = "SELECT Id,Nome,Endereco,Telefone,Email,Observacao FROM Clientes WHERE Id = " & id
Dim tabela As New DataTable
tabela = AcessoDB.GetDataTable(sql)
Return GetCliente(tabela)
Catch ex As Exception
Throw ex
End Try
End Function
Public Function GetCliente(ByVal tabela As DataTable) As Cliente
Try
Dim _Cliente As New Cliente
If tabela.Rows.Count > 0 Then
_Cliente.Id = tabela.Rows(0).Item(0)
_Cliente.nome = tabela.Rows(0).Item(1)
_Cliente.endereco = tabela.Rows(0).Item(2)
_Cliente.telefone = tabela.Rows(0).Item(3)
_Cliente.email = tabela.Rows(0).Item(4)
_Cliente.observacao = tabela.Rows(0).Item(5)
Return _Cliente
Else
_Cliente = Nothing
Return _Cliente
End If
Catch ex As Exception
Throw ex
End Try
End Function
Public Function Exibir() As List(Of Cliente) Implements ICliente(Of Cliente).Exibir
Try
Dim sql As String = "SELECT * FROM Clientes"
Dim tabela As New DataTable
tabela = AcessoDB.GetDataTable(sql)
Return GetListaCliente(tabela)
Catch ex As Exception
Throw ex
End Try
End Function
Public Function GetListaCliente(ByVal tabela As DataTable) As List(Of Cliente)
Try
Dim listaCliente As New List(Of Cliente)
Dim i As Integer = 0
Dim registros = tabela.Rows.Count
If registros > 0 Then
For Each drRow As DataRow In tabela.Rows
Dim _Cliente As New Cliente
_Cliente.Id = tabela.Rows(i).Item(0)
_Cliente.nome = tabela.Rows(i).Item(1)
_Cliente.endereco = tabela.Rows(i).Item(2)
_Cliente.telefone = tabela.Rows(i).Item(3)
_Cliente.email = tabela.Rows(i).Item(4)
_Cliente.observacao = tabela.Rows(i).Item(5)
listaCliente.Add(_Cliente)
Next
While i <= registros
Dim _Cliente As New Cliente
_Cliente.Id = tabela.Rows(i).Item(0)
_Cliente.nome = tabela.Rows(i).Item(1)
_Cliente.endereco = tabela.Rows(i).Item(2)
_Cliente.telefone = tabela.Rows(i).Item(3)
_Cliente.email = tabela.Rows(i).Item(4)
_Cliente.observacao = tabela.Rows(i).Item(5)
listaCliente.Add(_Cliente)
i += i
End While
Return listaCliente
Else
listaCliente = Nothing
Return listaCliente
End If
Catch ex As Exception
Throw ex
End Try
End Function
Public Function ConsultarPorID(id As Integer) As DataTable Implements ICliente(Of Cliente).ConsultarPorID
Dim sql As String = "SELECT Id,Nome,Endereco,Telefone,Email,Observacao FROM Cliente WHERE Id = " & id
Try
Return AcessoDB.GetDataTable(sql)
Catch ex As Exception
Throw ex
End Try
End Function
Public Function Consultar(nome As String) As DataTable Implements ICliente(Of Cliente).Consultar
Dim sql As String = "SELECT Id,Nome FROM Cliente WHERE Nome LIKE '" & nome & "%'" & " ORDER BY Nome"
Try
Return AcessoDB.GetDataTable(sql)
Catch ex As Exception
Throw ex
End Try
End Function
Public Sub Incluir(oCliente As Cliente) Implements ICliente(Of Cliente).Incluir
Dim sql As String = ""
Try
Dim parametrosNomes(5) As String
parametrosNomes(0) = "@Nome"
parametrosNomes(1) = "@Endereco"
parametrosNomes(2) = "@Telefone"
parametrosNomes(3) = "@Email"
parametrosNomes(4) = "@Observacao"
Dim parametrosValores(5) As String
parametrosValores(0) = oCliente.nome
parametrosValores(1) = oCliente.endereco
parametrosValores(2) = oCliente.telefone '
parametrosValores(3) = oCliente.email
parametrosValores(4) = oCliente.observacao
sql = "INSERT INTO Cliente(Nome,Endereco,Telefone,Email,Observacao) values (@Nome,@Endereco,@Telefone,@Email,@Observacao)"
AcessoDB.CRUD(sql, parametrosNomes, parametrosValores)
Catch ex As Exception
Throw ex
End Try
End Sub
Public Sub Alterar(oCliente As Cliente) Implements ICliente(Of Cliente).Alterar
Dim sql As String = ""
Try
Dim parametrosNomes(6) As String
parametrosNomes(0) = "@Id"
parametrosNomes(1) = "@Nome"
parametrosNomes(2) = "@Endereco"
parametrosNomes(3) = "@Telefone"
parametrosNomes(4) = "@Email"
parametrosNomes(5) = "@Observacao"
Dim parametrosValores(6) As String
parametrosValores(0) = oCliente.Id
parametrosValores(1) = oCliente.nome
parametrosValores(2) = oCliente.endereco
parametrosValores(3) = oCliente.telefone '
parametrosValores(4) = oCliente.email
parametrosValores(5) = oCliente.observacao
sql = "UPDATE Cliente SET Nome=@Nome, Endereco=@Endereco ,Telefone=@Telefone,Email=@Email , Observacao=@Observacao Where Id=@Id"
AcessoDB.CRUD(sql, parametrosNomes, parametrosValores)
Catch ex As Exception
Throw ex
End Try
End Sub
Public Sub Excluir(oCliente As Cliente) Implements ICliente(Of Cliente).Excluir
Dim sql As String = ""
Try
Dim parametrosNomes(0) As String
parametrosNomes(0) = "@Id"
Dim parametrosValores(0) As String
parametrosValores(0) = oCliente.Id
sql = "DELETE FROM Cliente Where Id=@Id"
AcessoDB.CRUD(sql, parametrosNomes, parametrosValores)
Catch ex As Exception
Throw ex
End Try
End Sub
Public Function ExibirTodos() As DataTable Implements ICliente(Of Cliente).ExibirTodos
Dim sql As String = "SELECT * FROM Clientes"
Try
Return AcessoDB.GetDataTable(sql)
Catch ex As Exception
Throw ex
End Try
End Function
End Class
|
Note que os métodos usam a classe AcessoDB seguida do nome do método desejado.
Eu estou usando instruções SQL no formato texto definindo a instrução em uma variável. Outra opção seria utilizar stored procedures que teria algumas vantagens.
Agora podemos definir as funcionalidades da camada de apresentação - UI - que irá usar os recursos das demais camadas.
É isso que faremos na última parte do artigo.
Flp 1:27 Somente portai-vos, dum modo digno do evangelho de Cristo, para que, quer vá e vos veja, quer esteja ausente, ouça acerca de vós que permaneceis firmes num só espírito, combatendo juntamente com uma só alma pela fé do evangelho;
Flp 1:28 e que em nada estais atemorizados pelos adversários, o que para eles é indício de perdição, mas para vós de salvação, e isso da parte de Deus;
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
VB 2005 - Introdução a concorrência de dados - Macoratti.net
ADO .NET - Verificando a violação de concorrência - Macoratti.net
Arquitetura de dados desconectada e a concorrência - Macoratti.net