Portando o Sistema de Controle de Usuários para o SQL Server
Olá pessoal! E aí, tudo indo bem?
Recentemente na empresa em que eu trabalho tivemos a necessidade de fazer um controle de acesso para um dos sistemas que estamos desenvolvendo. Este sistema é web, utilizando a tecnologia ASP.NET, e como eu já tinha o controle de usuários prontinho, só foi pegar ele daqui do N.M. Tech e implementar no programa, certo?
Em partes, explico o porquê:
Para implementar as telas em ASP.NET, foi sem maiores problemas, bastou alterar o CSS da página, e alguns outros detalhes.
Com as classes, a história foi um pouquinho diferente. Além de colocar os arquivos no projeto e alterar o namespace dos mesmos, tive um pequeno problema com algumas particularidades do banco de dados (no caso era o SQL Server), pois o Controle de Acesso é baseado em Firebird, e por conta disso alguns probleminhas em algumas instruções nas classes também. Vamos detalhá-los:
- Modificações no Banco de Dados:
Na parte da estrutura do banco de dados, além da sintaxe e de alguns tipos de dados, no SQL Server não temos generators e as exceptions disparadas pelo usuário funcionam de forma diferente.
O problema com a falta de generators, que utilizei no Firebird para fazer o auto-incremento dos campos, foi resolvido declarando o campo que iria ser alimentado com o valor do generator como identity (que é auto-incrementado) no SQL Server. Veja como ficou a tabela USUARIOS, para ter uma idéia:
1: /*Original em Firebird*/
2: create generator GEN_USUARIO_ID;
3: create table USUARIOS (
4: USUARIO_ID integer not null primary key,
5: NOME varchar(100),
6: LOGIN varchar(15),
7: PERFIL_ID integer,
8: SENHA BLOB sub_type 0 segment size 80,
9: STATUS char(1) default 'A'
10: );
11:
12: /*Como ficou no SQL Server*/
13: create table USUARIOS (
14: USUARIO_ID int not null primary key identity,
15: NOME varchar(100),
16: LOGIN varchar(15),
17: PERFIL_ID integer,
18: SENHA image,
19: STATUS char(1) default 'A'
20: );
O campo SENHA da tabela USUARIOS foi declarado como image (que é um BLOB) no SQL Server.
Outra coisa que teve modificação drástica do FB para o SQL Server foi a procedure SP_INSERE_USUARIO. Ela foi modificada por causa da exception EXC_EXISTE_USUARIO, que é criada no Firebird, porém no SQL Server não temos o comando create exception, e sim a função Raise_Error que é utilizada dentro da procedure.
Portanto, esta função foi usada no SQL Server para disparar a mensagem de erro de usuário existente. Veja como ficou:
1: /*Original em Firebird:*/
2: CREATE EXCEPTION EXC_EXISTE_USUARIO 'Login já existente no sistema. Indique outro :-)';
3: SET TERM ^ ;
4:
5: CREATE PROCEDURE SP_INSERE_USUARIO (
6: nome varchar(100),
7: login varchar(15),
8: perfil_id integer,
9: senha blob sub_type 0 segment size 80,
10: status char(1))
11: returns (
12: usuario_id integer)
13: as
14: begin
15: if (not exists(select * from USUARIOS where LOGIN = :login)) then
16: begin
17: usuario_id = gen_id(gen_usuario_id,1);
18: insert into USUARIOS (USUARIO_ID,NOME, LOGIN, PERFIL_ID, SENHA, STATUS)
19: values (:usuario_id, :nome, :login, :perfil_id, :senha, :status);
20: end
21: else begin
22: exception exc_existe_usuario;
23: end
24: suspend;
25: end^
26:
27: SET TERM ; ^
28:
29: /*Como ficou no SQL Server*/
30: CREATE PROCEDURE SP_INSERE_USUARIO (
31: @nome varchar(100),
32: @login varchar(15),
33: @perfil_id int,
34: @senha image,
35: @status char(1), @usuario_id int output
36: )
37: AS
38:
39: if (not exists(select * from USUARIOS where LOGIN = @login))
40: begin
41: insert into USUARIOS (NOME, LOGIN, PERFIL_ID, SENHA, STATUS) values
42: (@nome, @login, @perfil_id, @senha, @status);
43: select @USUARIO_ID = @@IDENTITY;
44: end
45: else begin
46: Raiserror('Login já existente no sistema. Indique outro :-)',16,1);
47: end
Note também uma inversão de instruções: No Firebird, primeiro geramos o ID da tabela com a função gen_id, que recebe como parâmetros o generator a ser incrementado e o fator de incremento, e guardamos o valor na variável usuario_id.
Já no SQL Server, primeiro executamos a instrução INSERT e em seguida pegamos o valor do IDENTITY gerado através de uma instrução select, onde guardamos na variável @USUARIO_ID o valor do ultimo identity gerado através da função @@IDENTITY.
Da parte do BD, é isso, agora vamos às classes :-)
As modificações nas classes foram necessárias por causa de algumas particularidades das instruções SQL utilizadas, que funcionavam no Firebird mas não no SQL Server.
Nas instruções de UPDATE das classes de Perfil e Usuário, originalmente declaramos as chaves primárias (USUARIO_ID e PERFIL_ID), que são auto-incrementadas, na cláusula SET da instrução SQL.
O Firebird simplesmente ignorava, enquanto que no SQL Server uma mensagem informando que campos declarados como identity não poderiam ser inclusos na cláusula SET de uma instrução de update. Os mesmos foram removidos da instrução.
Também teve uma pequena modificação na sintaxe do comando de execução de stored procedure via SQL. No Firebird, utilizamos a sintaxe "execute procedure nome_da_sp(<lista de parâmetros separados por vírgula)", enquanto que no SQL Server utilizamos a seguinte sintaxe: "execute nome_da_sp <lista de parâmetros separados por espaço>".
Estas modificações farão a classe funcionar nos dois bancos de dados, seguindo a ressalva deste comando de execução de SP, bastando fazer um "if" conforme o BD :-)
Após isso, caso queira somente mudar o mecanismo de banco de dados, utilizando uma biblioteca de classes somente para o Controle de Acesso, ela (como qualquer projeto em que a classe Conexao é utilizada em sua forma original) deve ser compilada seguindo as diretrizes da Classe Conexao (o nosso motor de SQL):
Uma chave chamada "strConexao" deverá ser criada no seu arquivo web.config (para aplicações ASP.NET), e o seu valor deve ser a string de conexão referente ao banco de dados utilizado. Deve ficar assim:
1: <appSettings>
2: <add key="strConexao" value="Data Source=LOCALHOST\SQLEXPRESS;Initial Catalog=USER_CONTROL;
3: Integrated Security=SSPI;persist security info=False;Trusted_Connection=Yes"/>
4: </appSettings>
Esta string de conexão é utilizada para o SQL Server, com autenticação Windows Authentication. Uma boa referência sobre strings de conexão (que é a minha referência, por sinal) é o site Connection Strings.
A Classe Conexao também manda utilizar uma diretiva de compilação conforme o banco de dados a ser utilizado. Para isso, clique com o botão direito sobre o projeto da biblioteca de classes onde se encontra a classe Conexao e selecione a opção Properties. Selecione a guia "Build" na janela em que se abre, e no textbox "Conditional Compilation Symbols" coloque a diretiva correspondente ao provider a ser utilizado:
- SQL Server (utilizando o provider em System.Data.SqlClient): SQLSERVER
- Oracle (utilizando o provider em System.Data.OracleClient): ORACLE
- Firebird (utilizando o provider FirebirdSql.Data.FirebirdClient, podendo ser obtido no site do Firebird): FIREBIRD
- Bancos conectados via ODBC (utilizando o provider System.Data.Odbc): ODBC
- Bancos conectados via OLEDB (utilizando o provider System.Data.OleDb): OLEDB
Veja onde deve ser alterado, no Visual Studio:
Não se esqueça de colocar a referência do provider utilizado no projeto da biblioteca de classes!
Para facilitar o trabalho, clique aqui para pegar o exemplo já portado para o SQL Server, contendo os scripts de criação da base de dados, uma base de dados exemplo (com um usuário cadastrado, chamado "teste", com a senha "teste"), que deve ser atachada ao seu servidor SQL, e a aplicação em si (bibliotecas de classe e o exemplo web).
Ao utilizar o exemplo, não se esqueça de setar a página "login.aspx" como a página inicial do projeto Web!
Logo logo penso em fazer um port para Windows Forms, onde vai ser só migrar a interface de usuário, não as classes ;-)
Um grande abraço a todos, e mais uma vez agradecimentos aos feedbacks positivos que venho recebendo deste site :-)
0 comentários:
Postar um comentário