Exemplo de uso do Framework SQL
Olá pessoal! Agora sim, sai o exemplo de utilização do framework SQL que apresentei nos primeiros artigos deste blog!
O programa consiste em demonstrar as operações básicas (select, insert e update) da classe Conexao através de um mini-cadastro de clientes.
São poucos campos, mas não importa, é o mesmo procedimento para tabelas maiores ;-)
A aplicação está preparada para rodar em banco de dados Firebird e SQL Server, o que vai definir qual BD a aplicação irá rodar depende de apenas uma configuração no arquivo web.config.
No arquivo, disponibilizo:
- Aplicativo Web (as telas não estão formatadas, já que o principal intuito do programa é a demonstração da classe de Conexao).
- Bibiliteca de Classes, que é o núcleo da aplicação. A camada que trata as regras e a conexão com o banco de dados. Além da classe Conexao (o nosso Framework SQL), temos um arquivo Consts.Funcoes.cs, que contém funções que costumo utilizar sempre, principalmente para conversão de objetos nulos em valores padrão.
- Arquivo Firebird 2.0 (.fdb) com o banco de dados.
- Arquivo SQL Server 2005 (.mdf e .ldf) - usei o SQL Server 2005 Express para a criação.
O projeto foi feito no Visual Studio 2005 e você precisará dos seguintes componentes instalados:
- Extensões AJAX (ASP.NET Ajax)
- Firebird Client 2.0.1 (pode ser mais recente, porém a referência precisará ser refeita)
O arquivo está disponível na seção de downloads do blog: Página de Suporte do NeoMatrix Tech no final do post.
Para acompanhar o artigo, sugiro que façam o download do mesmo, pois "resumi" bastante o código aqui.
Antes, um pequeno adendo referente as alterações que precisei fazer na classe Conexao:
Quando compilamos um projeto com suporte a mais de um mecanismo de banco de dados, o VS informa um erro de variável declarada múltiplas vezes.
O erro ocorria quando nas propriedades do projeto da biblioteca de classes habilitávamos mais de um mecanismo de BD a variável TipoBD era declarada múltiplas vezes, acompanhem:
1: public class Conexao
2: {
3: ...
4: #if FIREBIRD
5: public static TTipoBancoDados TipoBD = TTipoBancoDados.tbFireBird;
6: #endif
7: #if SQLSERVER
8: public static TTipoBancoDados TipoBD = TTipoBancoDados.tbSQLServer;
9: #endif
10: ...
11: }
Com as duas diretivas informadas, o código de declaração da variável TipoBD se repetia, coisa que não acontece quando usamos suporte a apenas um mecanismo de banco de dados.
Solução:
Se vocês notaram, a classe Conexao não possui um construtor declarado. A primeira coisa que eu fiz foi declarar este construtor, de maneira que quando instanciamos Conexao a partir de uma classe derivada, o código fosse executado.
Com isso, declarei a variável TipoBD fora do construtor (continua sendo uma variável estática, de classe) e a atribuição do tipo de BD referente a diretiva de compilação foi colocada dentro do construtor. Mas aí ainda tinha um problema: Quando executado com suporte a mais de um BD, era sempre a última atribuição que ficava. Fiz um código que pega, a partir de uma chave no arquivo de configuração da aplicação, determinasse qual banco de dados a aplicação irá utilizar.
O código final ficou:
1: public class Conexao
2: {
3: protected static TTipoBancoDados TipoBD;
4: public Conexao()
5: {
6: #if FIREBIRD
7: /// <sumarry>
8: /// Indica o banco de dados a ser utilizado na aplicação. Basta definir aqui e todos os objetos herdeiros irão utilizar este banco.
9: /// </sumarry>
10: TipoBD = TTipoBancoDados.tbFireBird;
11: #endif
12: #if ORACLE
13: /// <sumarry>
14: /// Indica o banco de dados a ser utilizado na aplicação. Basta definir aqui e todos os objetos herdeiros irão utilizar este banco.
15: /// </sumarry>
16: TipoBD = TTipoBancoDados.tbOracle;
17: #endif
18: #if SQLSERVER
19: /// <sumarry>
20: /// Indica o banco de dados a ser utilizado na aplicação. Basta definir aqui e todos os objetos herdeiros irão utilizar este banco.
21: /// </sumarry>
22: TipoBD = TTipoBancoDados.tbSQLServer;
23: #endif
24: #if ODBC
25: /// <sumarry>
26: /// Indica o banco de dados a ser utilizado na aplicação. Basta definir aqui e todos os objetos herdeiros irão utilizar este banco.
27: /// </sumarry>
28: TipoBD = TTipoBancoDados.tbODBC;
29: #endif
30: #if OLEDB
31: /// <sumarry>
32: /// Indica o banco de dados a ser utilizado na aplicação. Basta definir aqui e todos os objetos herdeiros irão utilizar este banco.
33: /// </sumarry>
34: TipoBD = TTipoBancoDados.tbOleDb;
35: #endif
36: if (ConfigurationManager.AppSettings["BD"] != null)
37: {
38: string bd = ConfigurationManager.AppSettings["BD"] != null ? ConfigurationManager.AppSettings["BD"].ToString().ToUpper() : "FB";
39: switch (bd)
40: {
41: case "FIREBIRD": { TipoBD = TTipoBancoDados.tbFireBird; break; }
42: case "SQLSERVER": { TipoBD = TTipoBancoDados.tbSQLServer; break; }
43: case "ORACLE": { TipoBD = TTipoBancoDados.tbOracle; break; }
44: case "OLEDB": { TipoBD = TTipoBancoDados.tbOleDb; break; }
45: case "ODBC": { TipoBD = TTipoBancoDados.tbODBC; break; }
46: default: goto case "FIREBIRD";
47: }
48: }
49: ...
50: }
Com isso, caso a aplicação necessite rodar em mais de um mecanismo de banco de dados, deverá existir no seu arquivo de configuração uma chave chamada "BD", e o valor é a diretiva de compilação correspondente ao banco de dados que se queira utilizar.
Caso necessite de apenas um mecanismo, o mesmo é determinado pela própria diretiva de compilação, como era feito antes, sem a necessidade do atributo BD no arquivo de configuração.
O arquivo corrigido está disponível para download na área de suporte do blog (link acima)
Agora, vamos a uma breve descrição do exemplo:
Primeiramente, temos uma bibiloteca de classes que é a responsável pela busca e gravação dos registros no Banco de Dados. Em seguida, uma interface web que faz referência a esta biblioteca de classes.
Criei uma classe chamada TCliente, cujas propriedades são os campos da tabela, e possui métodos de pesquisa, setar as propriedades através de um ID, exclusão, inclusão e alteração.
O método de inclusão, demonstra também como utilizar stored procedures do BD através das propriedades e métodos da classe Conexao e a captura dos valores de retorno.
Os métodos também exploram o conceito de instruções SQL parametrizadas, com declaração de parâmetros, montagem de filtros e execução.
Veja como ficou simples o código.
Do lado da aplicação web, na primeira página, temos campos de filtro e dois botões. Um deles executa a pesquisa e retorna os resultados para um GridView. Outro encaminha para uma página de manutenção de registros. Nestas páginas, não temos nenhuma referência à web.config, providers de bancos de dados e tal, somente chamadas à classe TCliente.
Entendendo o código:
Em TCliente, primeiramente declarei as variáveis privadas, é com elas que iremos manipular os dados dentro da classe. Elas estão expostas através de propriedades, para que outras classes possam atribuir e receber valores. Temos dois construtores, um construtor básico, sem parâmetros, que simplesmente executa o construtor da superclasse; e outro construtor em que passamos um ID para carga de dados.
- Método SetByID:
Este método recebe um código de cliente e tras os seus dados para as propriedades de uma instância de TCliente. Ele faz o uso do método Select() da classe Conexao: É definido no atributo _Select a instrução SQL responsável por trazer os dados de um único registro da tabela Clientes. Ele é definido como uma query parametrizada da seguinte forma:
1: _SelectSQL = "select * from CLIENTES where CODIGO_CLIENTE = @PCLIENTE";
Com esta instrução, limpamos a lista de parâmetros SQL de Conexao e alimentamos com o parâmetro "@PCLIENTE" e chamamos a instrução _Select(true). Se executada com sucesso, todos os campos da tabela serão retornados na coleção ListaCamposTabela, e podemos atribuir os valores dos itens dela para as propriedades de TCliente. Como cada campo é indexado pelo nome em uma propriedade this[] indexada, usei a seguinte atribuição:
1: _CPF = Consts.Funcoes.NullOrString(this["CPF"]);
A função Consts.Funcoes.NullOrString garante que caso o campo venha nulo, seja atribuido para a propriedade uma string vazia, evitando o erro de tentativa de atribuição de null.
- Método Inserir()
Este método consiste em executar uma stored procedure utilizada para inserção do registro no banco de dados. O campo CODIGO_CLIENTE é auto-incrementado, ou seja, o usuário não tem controle deste valor. No Firebird, implementei-o através de um generator e no SQL Server, declarei-o como identity. A procedure pega o código a ser inserido, insere os valores no BD e volta no parâmetro de saída o código inserido.
Os parâmetros são declarados da forma usual, com AddSQLParam, e o resultado da procedure é obtido via coleção de objetos TCampoCadastro. Portanto, retornamos o resultado da SP em uma coleção deste tipo:
1: List<TCampoCadastro> procresults = executeStoredProcedure("SP_INSERIR_CLIENTE", true);
Muito importante saber a ordem de declaração dos parâmetros, já que para recuperá-los da coleção temos que saber seu índice.
- Método Atualizar()
Este método consiste em atualizar, através de uma instrução UPDATE, um registro do BD.
A instrução UPDATE é definida em _UpdateSQL, parametrizada, e os parâmetros declarados. Em seguida, é chamada uma sobrecarga do método Salvar() em que é indicada a operação de atualização e confirmada a instrução SQL parametrizada.
- Método Excluir()
Análogo ao método Atualizar(), porém o SQL é informado em _DeleteSQL e passado a opção de exclusão em Salvar().
- Método Pesquisar()
Retorna um dataview com o resultado da pesquisa com os filtros especificados nos parâmetros da função.
Escolhendo o BD a ser utilizado:
Abrindo o arquivo web.config, na seção AppSettings, temos o atributo obrigatório strConexao declarado. É nele em que você vai colocar a string de conexão referente ao banco de dados utilizado na aplicação. Há exemplos para Firebird e SQL Server usando Windows Authentication. Lembre-se que somente um deles poderá ser usado por vez.
Como estamos compilando o suporte a dois mecanismos de BD ao mesmo tempo, fez-se necessário a criação de um atributo BD para controlar qual o BD a ser utilizado. E note que tanto em um BD como em outro, o código é o mesmo, só mudando o arquivo de configuração.
Pronto, com este exemplo, você será capaz de executar as operações básicas da Classe de Conexão!!! :-)
Exemplo de uso do Framework de Conexão (354 KiB)
0 comentários:
Postar um comentário