Esse é um exemplo em C# que eu sempre passo para todo mundo que está começando na linguagem e quer aprender qualquer coisa um pouco mais complexa do que um "hello world".
Trata-se de um script / função que consulta um banco de dados e devolve o resultado, como um relatório, por e-mail. Então dois temas são abordados: conexão com o banco de dados consultando-o e envio de e-mail.
uso C# para me conectar com um banco de dados MS SQL Server e fazer uma query. O resultado da query é enviado por e-mail, como texto, no corpo do mesmo.
Originalmente escrevi esse programa como exemplo para um colega não programador, que já sabia programar um pouco, porém no VBA do Excel, e que já conhecia o Microsoft SQL Server muito bem e sabia fazer queries e trazê-las para uma planilha excel, mas não conhecia nada de C# e não tinha vivência como programador.
No entanto este tutorial também é destinado à webdesigners que precisam fazer um script para envio de e-mail, mas não querem se aprofundar no C#.
É um exemplo bem simples, e é mais simples ainda de se fazer no C#.
Se você precisar (com certeza vai) de algum relatório um pouco mais avançado que seja enviado por e-mail, pode fazer um script que consulte o banco de dados e devolva o resultado por e-mail, algo assim:
/*
esqueleto básico de uma aplicação do tipo console
*/
/*
textos que devem ser trocados, de acordo com a situação:
1)[[servidor]] Servidor do banco de dados MS SQL Server (host ou ip)
2)[[banco_de_dados]] Nome do banco de dados
3)[[login]] login do banco
4)[[senha]] senha do banco
5)[[tabela]] tabela, view ou procedure / sentença sql a ser executada
6)[[campo 1]],[[campo n]] campos 1 ... n do resultado da consulta a serem trazidos no texto
7)[[remetente]] remetente do e-mail
8)[[destinatario]] destinatário do e-mail
9)[[com copia]] com cópia para
10)[[servidor de e-mail]] Servidor de e-mail
11)[[login do email]] login do e-mail
12)[[senha do email]] senha do e-mail
*/
//essas estruturas depois da palavra using, do lado de fora da classe, chamam-se namespaces.
//Cada namespace é uma subdivisão de uma hierarquia de bibliotecas de classes, que se encontram em um arquivo
//namespaces podem ser de sistema, que já vem junto, podem ser feitos por você, ou podem ser comprados
//using um.namespace significa que nesse arquivo sendo editado agora você usará recursos que estão nesse namespace.
//a árvore completa de namespaces é tão grande que a microsoft tem um site onde você pode pesquisar, mais fácil do que colocar tudo num livro
using System; //este é o principal namespace, onde se encontram as funções básicas do sistema. Este é obrigatório.
using System.Collections.Generic; //este namespace serve para lider com coleções genéricas em memória. Não será usado aqui, e é desnecessário, mas o visual studio coloca automaticamente.
using System.Linq; //este namespace serve para fazer consultas "tipo sql" via C#, em coleções de memória. Pode ser usado com bancos de dados, mas não o usaremos aqui.
using System.Text; //este namespace serve para geração de textos longos e manipulação de arquivos de texto em geral. Este usaremos
using System.Data; //este namespace abstrai tudo o que tem a ver com bancos de dados e coleções de dados
using System.Data.SqlClient;//extensão da biblioteca acima, serve para conectar-se com o SQL Server
using System.Net.Mail; //namespace que serve para trabalhar com e-mails
//abaixo o namespace criado por você, toda aplicação ou biblioteca fica dentro de um namespace
namespace MandaConsultaEmail
{
//este é o nome da classe. Em um programa orientado a objetos as funções (equivalentes as sub's do vb que você já conhece) ficam agrupadas dentro de classes
class Program
{
//o método Main é o método principal de um programa executável, é o ponto de entrada
//toda a aplicação windows deve ter um método main como este
//ao dar dois cliques em um programa o windows executará o método Main do programa automaticamente
//esses argumentos dentro do método Main são parâmetros de linha de comando que você pode passar para o aplicativo
//o fato de ele ser estático significa que ele deve ser executado diretamente a partir da classe, e não a partir de um objeto da classe (explicação detalhada sobre diferença entre objeto e classe fica para um outro dia)
static void Main(string[] args)
{
//string builder é uma classe que fica dentro de system.text. Ela será usada para criarmos o resultado que você quer por e-mail
//stringbuilder é a classe e strb é o objeto (instância/exemplo) dessa classe
//classe é uma categoria de objetos, um esqueleto
//objeto, como o próprio nome diz, é um exemplo desta categoria
//classe //objeto
StringBuilder strb = new StringBuilder();
//se você tivesse uma classe chamada Carro, um objeto desta classe poderia ser um fusca verde placa ngc6417
//objetos de uma classe são construidos a partir da palavra new. Por exemplo new StringBuilder() cria um novo StringBuilder
//a função StringBuilder() que tem o mesmo nome da classe StringBuilder é chamada de construtor
SqlConnection oCon = new SqlConnection(@"Data Source=[[servidor]];Initial Catalog=[[banco_de_dados]];Persist Security Info=True;User ID=[[login]];Password=[[senha]]"); //cria um objeto de conexão com o banco
//ao criar um objeto de conexão uma string pode ser passada como parâmetro
//esta string é chamada de connection string e contém instruções para se conectar no SQL, como endereço da máquina, nome do banco, login e password.
//é comum colocar-se a string de conexão em um arquivo de configuração e não no código, assim se mudar a senha do banco não precisa recompilar o programa.
//preceder uma string com @ desabilita as sequências de escape. Usar esse recurso sempre que a string contiver slashes "\" (este foi um erro que cometi escrevendo esse tutorial, até cachorro velho esquece dessas besteirinhas)
SqlCommand oComm = new SqlCommand("select top 10 * from [[tabela]]", oCon);// cria um objeto-comando. Esse objeto servirá para disparar o comando no banco.
//como todo comando precisa de uma conexão onde exeutar, passamos oCon (o objeto de conexão criado) como segundo argumento
//objetos de comando se criam assim:
//new SqlCommand(comandos , conexão)
oCon.Open(); //antes de executar o comando deve-se abrir a conexão. não SEJE como eu, que sempre esqueço disso.
SqlDataReader dr = oComm.ExecuteReader(); //cria um leitor de dados e o armazena no objeto dr
//o SQLCommand oComm possui dois métodos principais, um ExecuteReader e o ExecuteNonQuery.
//o ExecuteNonQuery serve para executar comandos que não retornem dados, como insert, update, delete.
//o ExecuteReader serve para executar comandos que retornam dados trazendo esses registros
//o executereader cria um SQLDataReader internamente, por isso você não precisa dar o comando dr = new SQLDataReader. Um método que cria um objeto (não sendo o seu constructor) é chamado de factory method
//se o comando for retornar dados crie um SQLDataReader para varrer os dados com SqlDataReader dr = oComm.ExecuteReader().
//se não retornar dados não crie o datareader, use direto o oComm.ExecuteNonQuery()
//no C# os argumentos do if sempre deverão vir entre parênteses
if(dr.HasRows) //pergunto se o dr retornou alguma linha
{
while (dr.Read()) //read le uma linha e avança para a próxima, como uma barra de rolagem, mas ela só pode avançar, não pode retroceder
{
strb.Append(dr["[[campo1]]"].ToString() + " - " + dr["[[campo n]]"].ToString() + "\r\n"); //adicionando campo i e campo 2 (e uma quebra de linha) no stringbuilder, para cada linha trazida da consulta, exemplo:
//strb.Append(dr["cpf"].ToString() + " - " + dr["nome"].ToString() + "\r\n"); //adicionando cpf e nome (e uma quebra de linha) no stringbuilder, para cada linha trazida da consulta
//o DataReader dr pode ser indexado de duas formas, pelo nome do campo ou pelo número do campo, exemplo:
//dr["cpf"] trará o valor do CPF
//dr[0] trará o valor do primeiro campo
//dr[1] trará o segundo campo, a lista começa em 0
}
}
//saindo do loop temos que mandar o e-mail
MailMessage mailMessage = new MailMessage(); //cria um novo objeto do tipo MailMessage chamado mailMessage
//repare que o C# é sensível a maiúscula / minúscula, portanto mailMessage é diferente de MailMessage
//eu particularmente não gosto de colocar o nome de um objeto igual ao nome de sua classe, mas você encontrará muito disso
//você pode preceder seus objetos com uma abreviação do tipo de classe que eles são, por exemplo:
//MailMessage mmFuncionarios = new MailMessage();
mailMessage.From = new MailAddress("[[remetente]]"); //cria um objeto do tipo endereço de e-mail que é o e-mail do remetente
mailMessage.Sender = new MailAddress("[[remetente]]"); //remetente também
mailMessage.To.Add("[[destinatario]]"); ////e-mail do destinatário
mailMessage.CC.Add("[[com copia]]"); // é o com cópia
//a diferença entre sender e from eu não sei, deve-se pesquisar no msdn
mailMessage.Subject = "Assunto do email";
//joga todo o texto do stringbuilder para o corpo do e-mail, com a lista completa do que você quer
mailMessage.Body = strb.ToString();
//define se o corpo do e-mail será html ou não
mailMessage.IsBodyHtml = false;
//SmtpClient é uma classe que funciona como o outlook, é um client de SMTP (o protocolo de comunicação utilizado por e-mails)
SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = "[[servidor de e-mail]]"; //servidor de e-mail
smtpClient.Port = 587; //25; //porta, a 25 é a padrão de e-mail sem criptografia (era padrão na época deste tutorial, hoje o padrão é 587)
smtpClient.UseDefaultCredentials = true; //true em grande parte dos casos, a saber, se o servidor se autentica com NTLM ou baseado em Kerberos. Caso seja true, o servidor usará as credenciais do usuário logado antes de enviar o e-mail. Leia:
//http://msdn.microsoft.com/pt-br/library/system.net.mail.smtpclient.usedefaultcredentials(v=vs.110).aspx
//http://msdn.microsoft.com/pt-br/library/system.net.credentialcache.defaultcredentials(v=vs.110).aspx
//NetworkCredential é uma classe que cria objetos que agrupam login e senha de redes, funciona assim:
//new System.Net.NetworkCredential(login, senha);
//no caso estamos usando o login e senha da intranet para mandar e-mail pelo servidor da mandic, considerando que intranet@lidertel.com.br é um e-mail válido na mandic
smtpClient.Credentials = new System.Net.NetworkCredential("[[login do email]]", "[[senha do email]]");
//setar isso para true em caso de gmail ou outro provedor que use ssl
//smtpClient.EnableSsl = true;
smtpClient.Send(mailMessage); //usa o client para enviar o message
//depois de usar o connection, se não precisar mais, fexar e dar dispose()
oCon.Close();
oCon.Dispose();
//o certo é fazer o dispose dentro de um bloco try... finally, mas depois falaremos disso.
} //fim do método main
}//fim da classe Program
}//fim do namespace
//regras de boa conduta ao programar:
//1) métodos estáticos apenas quando forem ser executados por um programa de fora ou forem executados a partir da classe e valem para a classe inteira, independente do objeto
//2) métodos estáticos são stateless, ou seja, não devem alterar o estado interno dos objetos, campos e variáveis
//3) crie uma classe por arquivo.cs, sendo que o arquivo deve ter o mesmo nome que a classe
//4) métodos, variáveis, propriedades, campos, atributos, namespaces e classes devem ter nomes significativos
//5) identificadores compostos de mais de uma palavra devem ter a primeira letra de cada palavra em maiúscula
Ao escrever esse mini - tutorial me surpreendi com a quantidade de informação que precisa ser passada para uma pessoa nova em programação.
É diferente de uma pessoa nova em uma linguagem / ambiente / framework mas que já saiba programar o básico.
No caso desse exemplo, ele fazia uma consulta em umas tabelas do banco de dados do sistema Totvs RM Labore, retornando os dados em forma de texto no corpo do e-mail (podia muito bem ser um csv ou excel).
Omiti, obviamente, o nome do banco, da tabela e os parâmetros de conexão com o banco.
Esse é um tutorial sem passar pelas etapas "obrigatórias" de um tutorial de programação: palavras reservadas, declaração de variáveis, tipos de dados, operadores aritméticos, if ... etc não necessariamente nesta ordem.
Também muitas teorias são simplesmente ignoradas aqui: pulamos direto para a parte prática e o código.
Pelo menos o código está explicado linha a linha.
Comentários
Postar um comentário