C# - ListView - CRUD básico com SQL Server em 3 camadas - I
Neste artigo vamos recordar como realizar o CRUD básico usando o banco de dados SQL Server em uma aplicação Windows Forms aplicando uma arquitetura em camadas. |
Vamos realizar a manutenção de usuários que estão armazenados em uma tabela Usuarios no banco de dados chamado Cadastro.mdf no SQL Server.
Apresentando os modelo de dados
A seguir temos a figura exibindo a estrutura da tabela Usuarios e alguns dados que eu vou usar para testar o projeto.
O Script usado para gerar a tabela :
USE [Cadastro]
GO
CREATE TABLE [dbo].[Usuarios](
[UsuarioId] [int] IDENTITY(1,1) NOT NULL,
[Nome] [nvarchar](150) NOT NULL,
[Senha] [nvarchar](150) NOT NULL,
[Email] [nvarchar](150) NOT NULL,
CONSTRAINT [PK_Usuarios] PRIMARY KEY CLUSTERED
(
[UsuarioId] ASC
);
|
Neste exemplo vamos usar os recursos da ADO .NET e trabalhar com uma camada de acesso a dados e uma camada de negócios separando assim as funcionalidades da nossa aplicação. Mesmo em projetos pequenos esta é uma boa prática a qual você deve se habituar.
Apresentando a aplicação
Antes de iniciar o projeto vamos dar uma olhada no formulário principal e explicar algumas funcionalidades do mesmo.
Abaixo temos o formulário principal do projeto onde é realizada a manutenção dos usuários da tabela Usuarios:
O Controle ListView esta sendo usado para exibir e manipular os dados de forma que ao clicar em uma linha do controle os dados são exibidos nas caixas de texto do formulário. Além disso vamos aplicar o efeito zebrado no controle e formatar as colunas.
Estamos usando também uma camada de acesso a dados simples com os recursos da ADO .NET (sem LINQ nem Entity Framework) e uma camada de negócios de forma a ter uma arquitetura em 3 camadas onde:
Criando o projeto Windows Forms e os projetos Class Library
Vamos então criar um projeto do tipo Windows Forms App(.NET Framework) no VS 2017 Community no menu File -> New Project, com o nome WF_Crud;
A seguir no menu File-> Add -> New Project, vamos incluir dois projetos do tipo Windows Desktop -> Class Library(.NET Framework) com o nome BLL e DAL.
Nossa solução deverá conter 3 projetos conforme mostra a estrutura na janela Solution Explorer:
|
Referenciando os projetos
Neste projeto a nossa camada de interface (UI) vai acessar a camada de negócios e por sua vez vai acessar a camada de acesso a dados.
Como temos 3 projeto distintos precisamos referenciar as dependências entre os projetos para que cada projeto tenha acesso ao código do projeto do qual depende.
Clique com o botão direito sobre o projeto WF_Crud e a seguir em Add -> Reference;
Como o projeto WF_Crud precisa acessar o projeto BLL na janela Reference, selecione Projects e marque a opção BLL clicando a seguir no botão OK:
Repita a operação para o projeto BLL e marque o projeto DAL:
Pronto. Agora podemos implementar o código em cada projeto.
Criando a camada de acesso aos dados - DAL
No projeto DAL vamos incluir uma classe chamada AcessoHelper que será a nossa camada de acesso aos dados.
Esta classe vai implementar a interface IDisposable e vai usar os seguintes namespaces:
using System;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
A seguir vamos definir a classe AcessoHelper implementando a interface IDisposable. Geralmente implementamos esta interface quando vamos tratar com tipos não gerenciados cono conexões de banco de dados e mesmo com código gerenciado como as classe .NET como System.IO.FileStream e assim termos mais segurança de que os objetos serão liberados após sua utilização pelo coletor de lixo.
Dessa forma vamos declarar a nossa classe da seguinte forma:
public class AcessoHelper :
IDisposable {
private
DbConnection objConnection;
public enum
ConnectionState
public
AcessoHelper()
public void
Dispose() |
Neste código temos:
O construtor inicia os objetos e define a string de conexão e a conexão com o banco de dados. O próximo passo é definir o método GetStringConnection() que obtém a string de conexão:
public string GetStringConnection()
{
string strConexao = @"Data Source = Macoratti; Initial Catalog = Cadastro; Integrated Security = True";
// Retorna a string de conexão
return strConexao;
}
|
A próxima etapa será definir os métodos para acessar e persistir informações no banco de dados. Para tornar as coisas mais simples eu só vou definir os métodos que o projeto irá usar e o nosso projeto irá realizar as seguintes operações:
A seguir temos os métodos ExecuteNonQuery definidos na classe AcessoHelper da camada de acesso a dados:
public int ExecuteNonQuery(string query) { return ExecuteNonQuery(query, CommandType.Text, ConnectionState.FechaConexaoAoSair); } public int
ExecuteNonQuery(string query, CommandType commandtype) public int
ExecuteNonQuery(string query, ConnectionState connectionstate) public int
ExecuteNonQuery(string query, CommandType commandtype, ConnectionState
connectionstate) |
Porque definimos 4 métodos ExecuteNonQuery ?
Definimos 4 métodos sobrecarregados para ter mais flexibilidade de forma a podemos passar para o métodos parâmetros diferentes conforme a nossa necessidade. Assim temos:
Nosso projeto iremos usar somente a primeira opção mas eu resolvi deixar os demais métodos para você perceber uma característica de uma linguagem orientada a objetos : a sobrecarga de métodos.
A seguir temos a definição dos métodos ExecuteReader da camada de acesso a dados:
public DbDataReader ExecuteReader(string query)
{
return ExecuteReader(query, CommandType.Text, ConnectionState.FechaConexaoAoSair);
}
public DbDataReader ExecuteReader(string query, CommandType commandtype)
{
return ExecuteReader(query, commandtype, ConnectionState.FechaConexaoAoSair);
}
public DbDataReader ExecuteReader(string query, ConnectionState connectionstate)
{
return ExecuteReader(query, CommandType.Text, connectionstate);
}
public DbDataReader ExecuteReader(string query, CommandType commandtype,
ConnectionState connectionstate)
{
objCommand.CommandText = query;
objCommand.CommandType = commandtype;
DbDataReader reader = null;
try
{
if (objConnection.State == System.Data.ConnectionState.Closed)
objConnection.Open();
if (connectionstate == ConnectionState.FechaConexaoAoSair)
reader = objCommand.ExecuteReader(CommandBehavior.CloseConnection);
else
reader = objCommand.ExecuteReader();
}
catch (Exception ex)
{
throw (ex);
}
finally
{
objCommand.Parameters.Clear();
}
return reader;
} |
Aqui também definimos 4 métodos sobrecarregados mas na verdade o projeto irá usar somente o primeiro onde passamos somente a string de consulta para o método.
Além destes poderíamos definir também os métodos :
Nota: Vou deixar a implementação destes métodos em um arquivo texto na pasta DAL.
Como estamos vamos usar parâmetros nas instruções SQL e consultas precisamos definir um método para podermos passar os parâmetros que serão usados nas instruções SQL. Para isso vamos criar o método AddParameter() conforme mostrado a seguir:
public int AddParameter(string name, object value)
{
DbParameter p = objFactory.CreateParameter();
p.ParameterName = name;
p.Value = value;
return objCommand.Parameters.Add(p);
}
public int AddParameter(DbParameter parameter)
{
return objCommand.Parameters.Add(parameter);
}
|
Para encerrar vamos definir um método para gerar um Hash da senha de forma que vamos armazenar não o texto da senha mas o seu HASH aumentando assim a segurança da informação. Segue abaixo o código do método GerarHash que obtém um texto e retorna um hash do mesmo :
public string GerarHash(string Valor) { System.Security.Cryptography.SHA1Managed Sha = new System.Security.Cryptography.SHA1Managed(); Sha.ComputeHash(System.Text.Encoding.Default.GetBytes(Valor)); return Convert.ToBase64String(Sha.Hash); } |
Nota: Este método não deveria estar nesta classe pois ele trata da geração de Hash e não tem nada a ver com acesso aos dados. Aqui estamos violando o padrão SRP. Mas para ficar mais simples vou implementar o método aqui mesmo.
Com esses métodos já temos a camada de acesso a dados pronta para nos dar o suporte necessário para consultar e persistir informações.
A próxima etapa é definir uma camada de negócios para receber as instruções da camada de interface e por último definir a camada de interface e criar as requisições necessárias as demais camadas para acessar e persistir informações dos usuários.
Aguarde a próxima parte do artigo.
(disse Jesus) - "Porque
por tuas palavras serás justificado, e por tuas palavras serás condenado."
Mateus 12:37
Veja os
Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique
e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
ASP .NET Core 2 - MiniCurso Básico - Macoratti
ASP .NET Core - Macoratti
Conceitos - .NET Framework versus .NET Core - Macoratti
ASP .NET Core - Conceitos Básicos - Macoratti.net
ASP .NET Core MVC - CRUD básico com ADO .NET - Macoratti
ASP .NET Core - Implementando a segurança com ... - Macoratti.net
ASP .NET Core - Apresentando Razor Pages - Macoratti
Minicurso ASP .NET Core 2.0 - Autenticação com JWT - I - Macoratti
Minicurso ASP .NET Core 2.0 - Autenticação com JWT - II - Macoratti.net