Como criar uma DLL pelo Microsoft Visual Studio

Veja nesse artigo como criar e desenvolver uma Data Definition Language (DLL) através do ambiente de desenvolvimento Microsoft Visual Studio em conjunto com o padrão MVC (Model – View – Controller).

O objetivo principal desse artigo é aprimorar técnicas existentes de programação para que, no futuro, tenhamos uma eficiente e correta comunicação entre a DLL criada e um projeto de ambiente web

Para que seja desenvolvida a DLL é preciso, inicialmente, supor que ela assuma alguma funcionalidade e, nesse caso, ela será responsável por controlar as transações do aplicativo web para um banco de dados que, por padrão, pode ser o Microsoft SQL Server, desde que tenha instalado seu gerenciador, o chamado SQL Server Management Studio.

A proposta é criar um novo banco de dados com o nome de ServiceDesk (nome próprio que identificará facilmente a nova base de dados) e em sequência a tabela Funcionario, de acordo com o modelo de diagrama de classe apresentado na Figura 1.

Figura 1. Diagrama de Classe inicial para a criação da tabela Funcionario para o banco de dados

Criando Tabela no SQL Server

Para criar a tabela Funcionario no SQL Server Management Studio, caso a versão instalada esteja em inglês, é só clicar em New Query (nova consulta) e depois colocar o código descrito na Listagem 1. Finalmente, clique em Execute (localizado no canto superior) ou pressione a tecla F5 - que é a tecla de atalho para execução de comandos SQL.

CREATE TABLE [dbo].[Funcionario]( [fun_codigo] [int] IDENTITY(1,1) NOT NULL, [fun_nome] [varchar](70) NOT NULL, [fun_dtcontratacao] [datetime] NOT NULL, [fun_dtdemissao] [datetime] NOT NULL, [fun_ativo] [char](1) NOT NULL, [fun_senha] [varchar](15) NOT NULL, [fun_tipo] [char](1) NOT NULL, CONSTRAINT [PK_Funcionario] PRIMARY KEY CLUSTERED ( [fun_codigo] ASC )WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY]
Listagem 1. Comandos para a criação da tabela e da chave primária
Nota: Comandos descritos na Listagem 1 foram executados no SQL Management Studio 2005.

Após isso, é necessário que sejam inseridas algumas informações no interior do banco de dados, pois posteriormente a aplicação web pode ser responsável por trazer para o usuário ou enviar essas informações para a tabela e, com nenhuma informação, a aplicação retornará nula ou com erro.

Criando um Novo Projeto

Agora, depois de ter o Microsoft Visual Studio instalado, é preciso criar um novo projeto para a criação da DLL. Neste exemplo será utilizado a versão 10 deste ambiente de desenvolvimento. No menu superior (se a versão estiver em inglês) vá em FileNewProject (ArquivoNovoProjeto). Após isso, aparecerá uma janela para escolha da forma de um novo projeto: selecione a aba Windows para abrir o menu Windows Forms Control Library. Dê um Name (nome), Location (localização) e um Solution name (nome para solução), deixando selecionado a opção “Create directory for solution” (dizendo que é para criar um diretório para solução) e clique em OK, como mostra a Figura 2.

Figura 2. Janela de configurações para a criação de um novo projeto Windows Forms Control Library (Visual C#)

Depois, aparecerá um arquivo chamado UserControl1.cs que é padrão na hora da criação de um novo projeto Windows Forms Control Library. Esse arquivo criado e presente no Solution Explorer pode ser excluído do projeto.

Feito isso, é preciso criar três pastas (Folders): uma com o nome de Controller (que será a responsável pelo Controlador), a segunda com o nome de DAO (que será a responsável pelo acesso, envio e manipulação de dados) e a terceira com o nome de Model (que será a responsável pelo Modelo), como mostra a Figura 3.

Figura 3. Hierarquia do projeto no Solution Explorer, com as pastas criadas

Criação se Classes

A proposta agora é criar as classes dentro de cada pasta, na qual cada uma é responsável por fazer sua funcionalidade.

Na pasta DAO serão criadas as classes: Banco.cs e FuncionarioBD.cs , onde a classe FuncionarioBD.cs será responsável pela manipulação de dados e comandos de SQL (insert, update, delete), e a classe Banco.cs será responsável por conectar com o banco de dados.

Para a classe Banco.cs podemos implementar os códigos referentes a Listagem 2.

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.SqlClient; using System.Data; namespace ServiceDesk.DAO { internal class Banco { private string _strConexao; private SqlCommand _comandoSQL; protected SqlCommand ComandoSQL { get { return _comandoSQL; } set { _comandoSQL = value; } } private SqlConnection _conn; private SqlTransaction _transacao; protected Banco() { _strConexao = @"Data Source=localhost\sqlexpress;Initial Catalog=ServiceDesk; Persist Security Info=True;User ID=sa;Password=a12345z"; _conn = new SqlConnection(_strConexao); _comandoSQL = new SqlCommand(); _comandoSQL.Connection = _conn; } protected Banco(string stringConexao) { _strConexao = stringConexao; _conn = new SqlConnection(_strConexao); _comandoSQL = new SqlCommand(); _comandoSQL.Connection = _conn; } protected bool AbreConexao(bool transacao) { try { _conn.Open(); if (transacao) { _transacao = _conn.BeginTransaction(); _comandoSQL.Transaction = _transacao; } return true; } catch { return false; } } protected bool FechaConexao() { try { if (_conn.State == ConnectionState.Open) _conn.Close(); return true; } catch { return false; } } protected void FinalizaTransacao(bool commit) { if (commit) _transacao.Commit(); else _transacao.Rollback(); FechaConexao(); } ~Banco() { FechaConexao(); } protected int ExecutaComando(bool transacao) { if (_comandoSQL.CommandText.Trim() == string.Empty) throw new Exception("Não há instrução SQL a ser executada."); int retorno; AbreConexao(transacao); try { retorno = _comandoSQL.ExecuteNonQuery(); } catch(Exception ex) { retorno = -1; throw new Exception("Erro ao executar o comando SQL:", ex); } finally { if (!transacao) FechaConexao(); } return retorno; } protected int ExecutaComando(bool transacao, out int ultimoCodigo) { if (_comandoSQL.CommandText.Trim() == string.Empty) throw new Exception("Não há instrução SQL a ser executada."); int retorno; ultimoCodigo = 0; AbreConexao(transacao); try { ultimoCodigo = Convert.ToInt32(_comandoSQL.ExecuteScalar()); retorno = 1; } catch(Exception ex) { retorno = -1; throw new Exception("Erro ao executar o comando SQL: ", ex); } finally { if (!transacao) FechaConexao(); } return retorno; } protected DataTable ExecutaSelect() { if (_comandoSQL.CommandText.Trim() == string.Empty) throw new Exception("Não há instrução SQL a ser executada."); AbreConexao(false); DataTable dt = new DataTable(); try { dt.Load(_comandoSQL.ExecuteReader()); } catch(Exception ex) { dt = null; throw new Exception("Erro ao executar o comando SQL: ", ex); } finally { FechaConexao(); } return dt; } protected double ExecutaScalar() { if (_comandoSQL.CommandText.Trim() == string.Empty) throw new Exception("Não há instrução SQL a ser executada."); AbreConexao(false); double retorno; try { retorno = Convert.ToDouble(_comandoSQL.ExecuteScalar()); } catch(Exception ex) { retorno = -1; throw new Exception("Erro ao executar o comando SQL: ", ex); } finally { FechaConexao(); } return retorno; } } }
Listagem 2. Classe responsável pela conexão com o banco de dados e execução de comandos de SQL, enviar, retornar e manipular conexão com tratamentos de erros

Vamos entender a lógica por traz da Listagem 2:

Para a classe FuncionarioBD.cs será implementado os códigos referentes a Listagem 3.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ServiceDesk.Model; using System.Data; namespace ServiceDesk.DAO { internal class FuncionarioBD : Banco { internal FuncionarioBD() { } internal Funcionario Autenticar(int codigo, string senha) { ComandoSQL.Parameters.Clear(); ComandoSQL.CommandText = @"select * from FUNCIONARIO where fun_codigo = @codigo and fun_senha = @senha"; ComandoSQL.Parameters.AddWithValue("@codigo", codigo); ComandoSQL.Parameters.AddWithValue("@senha", senha); DataTable dt = ExecutaSelect(); if (dt != null && dt.Rows.Count > 0) { Funcionario f = new Funcionario(); f.Codigo = Convert.ToInt32(dt.Rows[0]["fun_codigo"]); f.Nome = dt.Rows[0]["fun_nome"].ToString(); f.DataContratacao = Convert.ToDateTime(dt.Rows[0]["fun_dtcontratacao"]); if (dt.Rows[0]["fun_dtdemissao"] == DBNull.Value) f.DataDemissao = null; else f.DataDemissao = Convert.ToDateTime(dt.Rows[0]["fun_dtdemissao"]); f.Ativo = Convert.ToChar(dt.Rows[0]["fun_ativo"]); f.Senha = dt.Rows[0]["fun_senha"].ToString(); f.Tipo = Convert.ToChar(dt.Rows[0]["fun_tipo"]); return f; } else return null; } internal int Gravar(Funcionario func) { ComandoSQL.Parameters.Clear(); if (func.Codigo == 0) //Novo registro ComandoSQL.CommandText = @"insert into Funcionario (fun_nome, fun_dtcontratacao, fun_ativo, fun_senha, fun_tipo) values (@nome, @datacontratacao, @ativo, @senha, @tipo)"; else //Alteração { ComandoSQL.CommandText = @"update FUNCIONARIO set fun_nome = @nome, fun_dtcontratacao = @datacontratacao, fun_dtdemissao = @datademissao, fun_ativo = @ativo, fun_senha = @senha, fun_tipo = @tipo where fun_codigo = @codigo"; ComandoSQL.Parameters.AddWithValue("@codigo", func.Codigo); if (func.DataDemissao == null) ComandoSQL.Parameters.AddWithValue("@datademissao", DBNull.Value); else ComandoSQL.Parameters.AddWithValue("@datademissao", func.DataDemissao); } ComandoSQL.Parameters.AddWithValue("@nome", func.Nome); ComandoSQL.Parameters.AddWithValue("@datacontratacao", func.DataContratacao); ComandoSQL.Parameters.AddWithValue("@ativo", func.Ativo); ComandoSQL.Parameters.AddWithValue("@senha", func.Senha); ComandoSQL.Parameters.AddWithValue("@tipo", func.Tipo); return ExecutaComando(false); } internal List<Funcionario> Obter(string palavraChave, char ativo) { ComandoSQL.Parameters.Clear(); ComandoSQL.CommandText = @"select fun_codigo, fun_nome, fun_dtcontratacao, fun_dtdemissao, fun_ativo, fun_senha, fun_ativo, fun_tipo from Funcionario where fun_ativo = @ativo and fun_nome like @palavra order by fun_nome"; ComandoSQL.Parameters.AddWithValue("@ativo", ativo); ComandoSQL.Parameters.AddWithValue("@palavra", "%"+palavraChave+"%"); DataTable dt = ExecutaSelect(); List<Funcionario> dados = null; if (dt != null && dt.Rows.Count > 0) { dados = new List<Funcionario>(); foreach(DataRow linha in dt.Rows) { Funcionario f = new Funcionario(); f.Codigo = Convert.ToInt32(linha["fun_codigo"]); f.Nome = linha["fun_nome"].ToString(); f.DataContratacao = Convert.ToDateTime(linha["fun_dtcontratacao"]); if (linha["fun_dtdemissao"] == DBNull.Value) f.DataDemissao = null; else f.DataDemissao = Convert.ToDateTime(linha["fun_dtdemissao"]); f.Ativo = Convert.ToChar(linha["fun_ativo"]); f.Senha = linha["fun_senha"].ToString(); f.Tipo = Convert.ToChar(linha["fun_tipo"]); dados.Add(f); } } return dados; } internal int Demitir(int codigoFuncionario) { ComandoSQL.Parameters.Clear(); ComandoSQL.CommandText = @"update Funcionario set fun_ativo = 'N', fun_demissao = @data where fun_codigo = @codigo"; ComandoSQL.Parameters.AddWithValue("@data", DateTime.Now); ComandoSQL.Parameters.AddWithValue("@codigo", codigoFuncionario); return ExecutaComando(false); } internal Funcionario Obter(int codigoFuncionario) { ComandoSQL.Parameters.Clear(); ComandoSQL.CommandText = @"select fun_codigo, fun_nome, fun_dtcontratacao, fun_dtdemissao, fun_ativo, fun_senha, fun_ativo, fun_tipo from Funcionario where fun_codigo = @codigo"; ComandoSQL.Parameters.AddWithValue("@codigo", codigoFuncionario); DataTable dt = ExecutaSelect(); if (dt != null && dt.Rows.Count > 0) { Funcionario f = new Funcionario(); f.Codigo = Convert.ToInt32(dt.Rows[0]["fun_codigo"]); f.Nome = dt.Rows[0]["fun_nome"].ToString(); f.DataContratacao = Convert.ToDateTime(dt.Rows[0]["fun_dtcontratacao"]); if (dt.Rows[0]["fun_dtdemissao"] == DBNull.Value) f.DataDemissao = null; else f.DataDemissao = Convert.ToDateTime(dt.Rows[0]["fun_dtdemissao"]); f.Ativo = Convert.ToChar(dt.Rows[0]["fun_ativo"]); f.Senha = dt.Rows[0]["fun_senha"].ToString(); f.Tipo = Convert.ToChar(dt.Rows[0]["fun_tipo"]); return f; } else return null; } } }
Listagem 3. Classe FunionarioBD que contém métodos para autenticação de funcionário, gravação, listagem, consulta (obtenção) de acordo com suas atividades

Agora, na pasta Controller, será criada a classe: FuncionarioController.cs, responsável por controlar a sua tabela, definindo as ações e regras de acesso, como se fosse uma validação interna entre a saída e entrada de dados. A classe FuncionarioController.cs será implementada conforme o código da Listagem 4.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ServiceDesk.Model; using ServiceDesk.DAO; namespace ServiceDesk.Controller { public class FuncionarioController { FuncionarioBD bd = new FuncionarioBD(); public Funcionario Autenticar(int codigo, string senha) { if (codigo > 0 && senha.Trim().Length > 0) return new FuncionarioBD().Autenticar(codigo, senha); else return null; } public FuncionarioController() { } public int Gravar(Funcionario func) { if (func.Nome.Trim().Length >= 3 && func.Ativo == 'S') { return bd.Gravar(func); } else return -1; } public List<Funcionario> Obter(char ativo = 'S') { if (ativo == 'S' || ativo == 'N') return bd.Obter("",ativo); else return null; } public Funcionario Obter(int codigoFuncionario) { return codigoFuncionario > 0 ? bd.Obter(codigoFuncionario) : null; } public int Demitir(int codigoFuncionario) { return bd.Demitir(codigoFuncionario); } } }
Listagem 4. Classe controladora responsável por fazer validações, operações e métodos como na autenticação, pesquisa, gravação e alteração antes que os dados sejam manipulados

Já na pasta Model será criada a classe Funcionario.cs, onde modelará as regras de negócio como se fosse um intermediário entre o lado Cliente e o lado Servidor e cada propriedade é responsável por receber e/ou enviar as informações. A classe Funcionario.cs será implementada de acordo com a Listagem 5.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ServiceDesk.Model { public class Funcionario { public Funcionario() { _codigo = 0; } #region Propriedades do Funcionario private int _codigo; public int Codigo { get { return _codigo; } set { _codigo = value; } } private string _nome; public string Nome { get { return _nome; } set { _nome = value; } } private DateTime _dataContratacao; public DateTime DataContratacao { get { return _dataContratacao; } set { _dataContratacao = value; } } private DateTime? _dataDemissao; public DateTime? DataDemissao { get { return _dataDemissao; } set { _dataDemissao = value; } } private char _ativo; public char Ativo { get { return _ativo; } set { _ativo = value; } } private string _senha; public string Senha { get { return _senha; } set { _senha = value; } } private char _tipo; public char Tipo { get { return _tipo; } set { _tipo = value; } } #endregion } }
Listagem 5. Classe responsável por obter ou enviar informações do Funcionário via Get e Set

Por fim, após ter criado todas as classes relativas a tabela Funcionário, o layout dos arquivos ficará como mostra a Figura 4.

Figura 4. Hierarquia do projeto, com as pastas e suas respectivas classes

Criando a DLL ServiceDesk

Finalmente, para que o projeto se transforme em uma DLL, basta dar um Build e salvar. Com isso, ela pode ser utilizada em qualquer projeto web ASP .NET.

Para anexar essa DLL criada a um projeto web ASP .NET, basta clicar com o botão direito em References do novo projeto e clicar em Add Reference..., como ilustra a Figura 5.

Figura 5. Caminho para referenciar a DLL criada para um novo projeto web

Feito isso, aparecerá uma janela, conforme mostra na Figura 6.

Figura 6. Janela de opções e confirmação de anexo de Referencias (que no caso é uma referencia a DLL)

Após ter selecionado o Project Name, basta dar OK e a DLL criada estará na futura aplicação web ASP . NET.

Nota: Sempre que houver quaisquer alterações na DLL durante a implementação do projeto web ASP .NET, é obrigatório dar um Build na DLL para que a mesma não apresente erros.

Artigos relacionados