Revista ecode10 Magazine

Aplicativos patrocinadores


Autor: Mauricio Junior
Publicado em: 7/27/2014 11:03:51 AM

Criando SELECT para comparar Datas


Olá pessoal, hoje eu vou falar um pouco sobre como fazer um select no banco de dados com o objetivo de comparar datas. É bem simples na verdade, só que você precisa ficar atento com alguns detalhes importantes.

Usado:
Linguagem de programação: C#
Ferramenta de desenvolvimento: Visual Studio
Plataforma: .NET Microsoft
Projeto tipo: Web / desktop

Antes de falar sobre o SELECT propriamente dito, quero mostrar porque usar DTO (Data Transfer Object) ao invés de parâmetros soltos com tipos primitivos. A melhor comunicação entre classes ou camadas é o DTO, isso porque facilita e organiza o trabalho do desenvolvedor.

Já falei isso em outros momentos, mas sempre é bom reforçar. Veja a listagem 1 com  dois métodos:

Listagem 1 - Métodos comuns
public DataTable BuscaNoticias (String nome, Int32 Id, DateTime dataPublicacao)
public String BuscaEmail(String nome)


O primeiro método busca as notícias passando o nome, id e data da publicação. O retorno do método é o objeto DataTable. O segundo método busca e-mail passando o nome e retorna uma String. Imagine que esses métodos estejam na camada de acesso a dados, só que existe a camada de negócio e interface; ou seja; os métodos terão que ser repetido nas duas outras camadas até chegar na camada de acesso a dados.

Amanhã o cliente do sistema pede para buscar as notícias mais visualizadas em um período de tempo. Para resolver o problema do cliente, você programador terá que alterar toda assinatura do método em cada camada e depois de alterar, testar, compilar e publicar todas as camadas no servidor. Usando DTO bastava alterar a camada de layout e de acesso a dados.

A publicação seria bem mais simples do que todas as camadas. Bastaria publicar a camada de acesso a dados e a camada de layout. 

Como colocar o primeiro e segundo método usando DTO? Basta criar uma classe DTO com propriedades e passar a mesma como parâmetro.

Listagem 2 - Passando as classes para usar DTO
Classe NoticiasDTO
public class NoticiasDTO
{
public String _nome {get; set; }
public Int32 _id {get; set; }
public DateTime _dataPublicacao {get; set;}
public DateTime _dataInicio {get; set;}
public DateTime _dataFim {get; set;}
}

public DataTable BuscaNoticias (NoticiasDTO dto)

Classe EmailDTO
public class NoticiasDTO
{
public String _nome {get; set; }
}

public String BuscaEmail (EmailDTO dto)


Depois de criar classes e mudar os parâmetros na assinatura do método, basta preencher o objeto antes e enviá-lo através das classes. Veja como fazer isso na listagem 3.

Listagem 3 - Preenchendo valores e chamando classe

//preenchendo valores da DTO
NoticiasDTO _noticiasDTO = new NoticiasDTO();
_noticiasDTO.Nome = ;
_noticiasDTO.Id = ;
_noticiasDTO.DataPublicacao= ;
_noticiasDTO.DataInicio = ;
_noticiasDTO.DataFim = ;

//chamando a classe de negocio
ClasseNegocio classe = new ClasseNegocio();
DataTable dt = classe.BuscaNoticias(_noticiasDTO);


Espero que tenha gostado dessa pequena explicando mostrando como enviar DTO pelas camadas ao invés de parâmetros separados. Depois de aprender tudo isso, vamos passar para o SELECT que busca informações entre datas específicas ou em um período de tempo.

É importante lembrar que para fazer um SELECT o banco de dados deve estar bem planejado e estruturado. Segue um exemplo na tabela 1.



Tabela 1 - Exemplo simples de um banco de dados.

Bom, esse é um exemplo bem simples de uma tabela do banco de dados chamada Noticias. Lá possui alguns campos essenciais para funcionar.

Para buscar uma notícia em certo período de tempo, você tem que usar o comando BETWEEN do SQL. Pode ser através do comando SELECT direto ou usando StoreProcedure. Vou mostrar hoje com o comando SELECT direto.

Listagem 4 - Método da camada de acesso a dados.
internal DataTable BuscaNoticias(NoticiasDTO dto)
{
            StringBuilder str = new StringBuilder();
            str.Append(@"
                        SELECT Id, Titulo, DataPublicacao, Conteudo FROM Noticias
  WHERE DataPublicacao BETWEEN @dataInicial AND @dataFinal
                       ");

           SqlCommand dbCommand = new SqlCommand(str.ToString());
            dbCommand.CommandType = CommandType.Text;

            IDataParameter dtInicial = new SqlParameter();
            dtInicial.ParameterName = "@dataInicial";
            dtInicial.Value = dto.DataInicio;
            dtInicial.DbType = System.Data.DbType.DateTime;
            dbCommand.Parameters.Add(dtInicial);

            IDataParameter dtFinal = new SqlParameter();
            dtFinal.ParameterName = "@dataFinal";
            dtFinal.Value = dto.DataFim;
            dtFinal.DbType = System.Data.DbType.DateTime;
            dbCommand.Parameters.Add(dtFinal);

//conecta com o banco de dados (usei o meu framework)
            getConnection();

//executa o comando executaDataSetParameter (usei o meu framework)
            return idTec.ExecutaDataSetParameter(dbCommand).Tables[0];
}

Explicando o método

Note que a listagem 4 declara na primeira linha um objeto StringBuilder. Esse objeto é melhor para criar a sequência de comandos SELECT. Antes de atribuir os valores, adicionei o @ (arroba) e aspas duplas, isso porque se o código for para a linha debaixo, não tem problema algum e assim não preciso ficar adicionando comandos para juntar linhas.

No SELECT, usei como parâmetro o @ e nome do parâmetro, por exemplo @dataInicial e @dataFinal. Essa é a melhor maneira de passar parâmetros a um SELECT com segurança. Hoje, o primeiro ato de hackers é o uso de SQL INJECT quando querem invadir um site. O INJECT é o uso de aspas simples e duplas com parâmetros entre elas.

Depois do SELECT preparado, vamos usar o SQLCommand para passar parâmetros e comandos ao banco de dados. Cada parâmetro há necessidade de informar o nome (o mesmo dentro do SELECT), valor vindo do DTO, tipo (o mesmo que está na classe) e depois adicionar ao SQLCommand. Ele pega tudo e manda para o banco de dados.

O comando dbCommand.CommandType = CommandType.Text; indica ao banco de dados que o tipo de comando enviado é texto. Você pode informa que o comando é uma procedure ao invés de texto, basta digitar ponto depois do CommandType e escolher a opção.

Para conectar ao banco de dados e executar o SQLCommand usei dois métodos específicos através do meu próprio framework. O método responsável por executar os dados com parâmetros está na listagem 5 para melhor entendimento.

Listagem 5 - Método do framework que executa os parâmetro no banco de dados
public DataSet ExecutaDataSetParameter(IDbCommand sqlCommand)
{
try
{
base.OpenConnection();
sqlCommand.Connection = sqlConnection;

System.Data.IDbDataAdapter dataAdapter = new System.Data.SqlClient.SqlDataAdapter();
dataAdapter.SelectCommand = sqlCommand;
DataSet dtSet = new DataSet();
dataAdapter.Fill(dtSet);
return dtSet;
}
catch(SqlException e)
{
throw new NotImplementedException(e.Message);
}
finally
{
base.CloseConnection();
}
}

Explicando cada linha do método

Note que a primeira linha é abrir o banco de dados. Depois pego a conexão pela variável sqlConnection e atribuo para o Command. Para executar DataSet, é necessário gerar um DataAdapter, por isso a criação da instância dataAdapter. Com o adapter, existe o método SelectCommand vindo como parâmetro.

Depois disso gerei um método do tipo DataSet e mandei o adapter preencher com o método Fill. Para trabalhar com DataTable ao invés de DataSet, basta colocar o ponto e escolher a opção Table[0], até porque não teremos outra tabela com linhas e colunas no SELECT. Tem como separar o select para o resultado vir em colunas e não linhas, mas isso é um papo para outro tipo de artigo. Veja a listagem 6.

Listagem 6 - Retornando DataTable
.Tables[0];

Bom, espero que tenha gostado do que leu. Não vou me estender mais para não ficar muito grande o artigo. Qualquer dúvida, favor entrar em contato pelo site www.mauriciojunior.org.
 
 

Anuncie seus apps conosco