terça-feira, 8 de dezembro de 2009

ADO.NET Entity Framework - Como gerar um DataTable a partir de uma query LINQ

Olá Pessoal

Neste Post, vou demonstrar como podemos gerar um DataTable a partir de uma query realizada com o LINQ utilizando ADO Data Entity.

Em determinadas situações como uma migração de sistema, por exemplo, necessitamos adaptar nosso código para trabalhar da maneira mais transparente possível e causando um menor impacto na aplicação. Vou dar um exemplo. Imagine uma aplicação onde a camada de dados faz um acesso a base e monta um DataTable devolvendo para a aplicação consumir. Nesta aplicação temos a necessidade de fazer uma migração para ADO.NET Entity Framework. Seria um impacto muito grande se, a princípio, tentássemos migrar a camada de dados e a aplicação junto para que, ao invés de DataTable, a aplicação passe a receber objetos do Entity Framework. Para isso, desenvolví uma pequena rotina para gerar DataTable a partir de uma query LINQ no Entity Framework.


A primeira parte é a query com o LINQ:

AdventureWorksEntities db = new AdventureWorksEntities();
IQueryable _query = (from c in db.Address
                    where c.City.Equals("Bothell", StringComparison.CurrentCultureIgnoreCase)
                    select new
                    {
                        ID = c.AddressID,
                        Endereco = c.AddressLine1,
                        Cidade = c.City,
                        CaixaPostal = c.PostalCode
                    }
                    ).OrderBy(o=>o.Endereco);

Reparem que no Retorno eu recebo um objeto do tipo IQueryable. Ele é uma interface que guarda os dados da query como: provider, expressão e os tipos de elemento que são retornados quando a expressão é executada. Como o retorno da query por definição implementa IQueryable, esta atividade fica transparente. O IQueryable também implementa IEnumerable, o que possibilita também percorrer a lista retornada pela query.



Eis o Método que transforma o objeto IQueriable em DataTable:

public static DataTable RetornarDataTable(IQueryable pObjQuery)
{
    DataTable _dt = new DataTable();

    //Cria o DataTable
    foreach (var item in pObjQuery)
    {
        Type t = item.GetType();
        PropertyInfo[] properties = t.GetProperties();
        for (int i = 0; i < properties.Length; i++)
        {
            _dt.Columns.Add(properties[i].Name);
        }
        break;
    }

    IEnumerator en = (IEnumerator)pObjQuery.GetEnumerator();

    //Popula o DataTable
    while (en.MoveNext())
    {
        Type ten = en.Current.GetType();
        PropertyInfo[] propertiesen = ten.GetProperties();
        DataRow _dtrow = _dt.NewRow();
        for (int i = 0; i < propertiesen.Length; i++)
        {
            object obj = propertiesen[i].GetValue(en.Current, new object[] { });
            _dtrow[i] = obj;
        }
        _dt.Rows.Add(_dtrow);
    }

    return _dt;
}


Reparem que neste código, procurei separar a montagem do DataTable, inclusive com os nomes das colunas fiéis a query, e logo após percorro a lista carregando os registros.


Abaixo o Código Completo para Testes:

static void Main(string[] args)
{
    DataTable _dtEnderecos = RetornarEnderecos();

    foreach (DataColumn col in _dtEnderecos.Columns)
    {
        Console.WriteLine(col.ColumnName);
    }
    Console.WriteLine("");
    foreach (DataRow dados in _dtEnderecos.Rows)
    {
        Console.WriteLine(dados["ID"] + " " + dados["Endereco"] + " " + dados["Cidade"] + " " + dados["CaixaPostal"]);
    }
    Console.Read();
}

public static DataTable RetornarEnderecos()
{
    AdventureWorksEntities db = new AdventureWorksEntities();
    IQueryable _query = (from c in db.Address
                        where c.City.Equals("Bothell", StringComparison.CurrentCultureIgnoreCase)
                        select new
                        {
                            ID = c.AddressID,
                            Endereco = c.AddressLine1,
                            Cidade = c.City,
                            CaixaPostal = c.PostalCode
                        }
                        ).OrderBy(o=>o.Endereco);

    return RetornarDataTable(_query);
}
public static DataTable RetornarDataTable(IQueryable pObjQuery)
{
    DataTable _dt = new DataTable();

    //Cria o DataTable
    foreach (var item in pObjQuery)
    {
        Type t = item.GetType();
        PropertyInfo[] properties = t.GetProperties();
        for (int i = 0; i < properties.Length; i++)
        {
            _dt.Columns.Add(properties[i].Name);
        }
        break;
    }

    IEnumerator en = (IEnumerator)pObjQuery.GetEnumerator();

    //Popula o DataTable
    while (en.MoveNext())
    {
        Type ten = en.Current.GetType();
        PropertyInfo[] propertiesen = ten.GetProperties();
        DataRow _dtrow = _dt.NewRow();
        for (int i = 0; i < propertiesen.Length; i++)
        {
            object obj = propertiesen[i].GetValue(en.Current, new object[] { });
            _dtrow[i] = obj;
        }
        _dt.Rows.Add(_dtrow);
    }

    return _dt;
}

A codificação é relativamente simples e de fácil implementação.

Até a Próxima...

sábado, 17 de outubro de 2009

Armazenando Strings em um Enum com com C#

Um Enum por definição, só armazena valores interiros. Com o Framework 3.5 temos um novo recurso chamado Extension Methods. Com esse recurso, é possível fazermos uma personalização  que nos permitirá o armazenamento de valores String no Enum.

Primeiro passo é a criação de um Atributo que irá armazenar os valores da string:
public static string GetStringValue(this Enum value)
{
    // Retorna o Tipo
    Type type = value.GetType();

    // Retorna informações do Campo deste Tipo
    FieldInfo fieldInfo = type.GetField(value.ToString());

    // Retorna os Atributos
    StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(
        typeof(StringValueAttribute), false) as StringValueAttribute[];

    // Retorna o primeiro se for encontrado
    return attribs.Length > 0 ? attribs[0].StringValue : null;
}
Depois, criar a classe Extension e o Extesion Method:
public static class MyExtension
{
    public static string GetStringValue(this Enum value)
    {
        // Get the type
        Type type = value.GetType();

        // Get fieldinfo for this type
        FieldInfo fieldInfo = type.GetField(value.ToString());

        // Get the stringvalue attributes
        StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(
            typeof(StringValueAttribute), false) as StringValueAttribute[];

        // Return the first if there was a match.
        return attribs.Length > 0 ? attribs[0].StringValue : null;
    }
}
Com isso, basta criar o Enum colocando os devidos atributos para armazenar as strings
public enum Test : int
{
    [StringValue("FOO_VALOR1")]
    Foo = 1,
    [StringValue("SOME_VALOR2")]
    Something = 2
}
Agora, basta Utilizar:
Test t = Test.Foo;
Console.WriteLine(t.GetStringValue());
É um recurso interessante para casos pontuais onde precisar armazenar strings para posterior utilização.

Até a próxima

Utilizando Enum no C#

Uma maneira muito prática para armazenamento de valores simbólicos que utilizam tipos de dados numéricos como byte, sbyte, short, ushort, int, uint, long ou ulong é a utilização do Enum. Com um Enum é possível armazenar um valor mais concreto que representa um número qualquer enriquecendo a utilização do componente, principalmente para terceiros.
Por exemplo, imagine que tenhamos um método que consulta uma pessoa na base de dados. A assinatura deste método tem dois parâmetros. O primeiro é um "int" que representa o tipo da consulta (1 = CPF, 2 = RG, 3 = Titulo Eleitor). O segundo é o argumento de pesquisa, conforme escolhido no primeiro parâmentro. Então, digamos que eu vou consultar por CPF, teria que passar:

object obj = c.Consultar(1, "222.222.222-77");

Agora, imagine que outro profissional irá utilizar sua classe para fazer a pesquisa, ele terá que recorrer a documentação para poder fazer uma simples consulta. Dependendo do tamanho da classe, pode gastar muito mais tempo tentando entender a documentação do que na implementação em sí.

Vamos melhorar essa consulta criando e utilizando um Enum:

enum EnumConsulta
{
    CPF = 1,   
    RG = 2,
    TituloEleitor = 3
}
No enum criado, por não ter sido tipado, ele assume o tipo "int". Caso queira tipar diferente:
enum EnumConsulta : byte
 

Depois mudando a consulta para aceitar no primeiro parâmetro um EnumConsulta ao invés de int, teremos o seguinte:

object obj = c.Consultar(EnumConsulta.CPF, "222.222.222-77");
Sempre que puder, utilizem este benefício do Enum, será muito útil para todos.

Até a próxima

Boxing e Unboxing em C#

O C#, como uma linguagem fortemente tipada, nos remete muitas vezes a precisarmos fazer conversões entre tipos de dados diferentes, o que chamamos de CAST. Chamamos de Boxing quando convertemos um tipos de dados "Value Type" para um "Reference Type". No caso do Unboxing, é exatamente ao contrário, ou seja, convertemos um tipo de dados "Reference Type" para um "Value Type".

Exemplo de Boxing:
int i = 9966;
object o = (object)i;

Exemplo de Unboxing:
object o = 9966;
int i = (int)o;

A prática de Boxing e Unboxing vem acompanhada de uma sobrecarga muito grande, portanto, deve ser evitada sempre que possível utilizando sempre os tipos específicos dos dados que deseja armazenar, sempre que tiver uma variação do tipo de dado a ser armazenado, uma boa prática é utilizar generics evitando qualquer tipo de conversão.

Até a próxima

domingo, 4 de outubro de 2009

Utilizando uma DLL .NET para objetos COM

Durante um processo de migração para a plataforma .NET, muitas das aplicações legadas acabam ficando pra traz. Com isso, uma necessidade de mudança de negócio pode provocar alterações tanto nas novas aplicações já desenvolvidas em .NET quanto no legado do mundo COM. A idéia deste artigo é uma demonstração de como é possível desenvolver uma DLL em .Net para ser aproveitada em um programa VB 6, por exemplo.

Assim como componentes COM podem ser consumidos por aplicações .NET, o inverso também é verdadeiro. Quando componentes .Net são consumidos por objetos COM, um proxy chamado "COM Callable Wrapper (CCW)" é responsável pela transformação de todos os ítens entre .NET e COM.

Para chegarmos ao objetivo, alguns passos devem ser seguidos:

1. Criar um Projeto "class library".


2. Abra a Janela "Project Properties" clicando o botão direito em "Project" e selecionando "Properties".


3. Clique na aba "Build".
4. Selecione a opção "Register For COM Interop" na seção "Output"



5. Dê um Build na aplicação e são gerados os seguinte arquivos:


Pronto, nesse ponto a aplicação está pronta para ser utilizada no mundo COM.

Vamos colocar algum código:

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class ClasseCOM
{
    private string _nome;

    [ComVisible(true)]
    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }
    [ComVisible(true)]
    public string NewGuidTeste()
    {
        return Guid.NewGuid().ToString();
    }
}


Com este código da maneira que está, só poderemos utilizar a DLL no formato Late Binding, ou seja, não teremos disponível a facilidade do intellisense.

Agora os passos necessários para fazer o Early Binging:

1. Deve ser criada uma interface com todos os membros que serão expostos e a classe que será utilizada deverá implementar esta interface
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class ClasseCOM : IClasseCOM
{
    private string _nome;

    [ComVisible(true)]
    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }
    [ComVisible(true)]
    public string NewGuidTeste()
    {
        return Guid.NewGuid().ToString();
    }
}
[ComVisible(true)]
public interface IClasseCOM
{
    [ComVisible(true)]
    string Nome { get; set; }
    [ComVisible(true)]
    string NewGuidTeste();
}

2. Deverá utilizar o comando "TlbExp.exe". Este comando "Type Library Exporter", será criado um arquivo .tlb para que possa ser consumido pela aplicação COM.

TlbExp.exe DLL_COM.dll




Agora, algumas regras para distribuição de DLLs COM:

1. Nenhuma classe deve ter parâmetros em seu construtor.
2. Todos os tipos que serão expostos devem ser publicos.
3. Todos os membros que serão expostos devem ser publicos.
4. Não é possível consumir classes abstratas.


Para utilizar a DLL em um aplicativo VB, basta seguir os seguintes passos:

1. Vá até Menu "Project
References...", depois clique em Browser e vá até o arquivo .tlb gerado anteriormente e o adicione.








Intellisense funcionando

2. Agora é só utilizar a DLL.

Até a Próxima

quinta-feira, 1 de outubro de 2009

Utilizando a Instrução MERGE no SQL Server

Uma novidade na parte DML do T-SQL é a instrução MERGE. Esta instrução tem como objeto principal dar mais flexibilidade para a parte ETL do SQL Server.

Basicamente, esta instrução faz um comparativo entre os dados de origem e o destino e permite disparar uma instrução DML em cima da análise que é executada deste comparativo. Por exemplo, Se a origem for correspondente com o destino, a instrução MERGE vai apenas fazer um UPDATE dos dados dentro do destino, esta é a primeira análise que será executada. Por outro lado, os dados da origem que não corresponderem com o destino, é realizado um INSERT dos novos dados na tabela de destino. Todo esse processo é realizado justamente com o objeto de evitar que haja redundância de informações, ou até mesmo um erro de violação de integridade dos dados que possam existir entre a origem e o destino. Caso a fonte de dados que está sendo usada para fazer o comparativo entre a origem e o destino não for correspondente, ou seja, o SQL identifica que dados do destino não existem na origem, será realizado um DELETE dos dados que estão sendo processados no destino.

Abaixo um exemplo da utilização do comando MERGE:

MERGE Stock S
 USING Trades T
 ON S.Stock = T.Stock
 WHEN MATCHED AND (Qty + Delta = 0) THEN
  DELETE
 WHEN MATCHED THEN
  UPDATE SET Qty = Delta
 WHEN NOT MATCHED THEN
  INSERT VALUES (Stock, Delta)

No Exemplo acima temos MERGE Stock, demos um apelido chamado "S" para referencia-lo mais a frente possibilitando esse processo de extração de dados entre fontes diferentes. Esta primeira é a origem.
Logo após temos uma instrução USING seguido da tabela Trades apelidada de "T" e esta será o destino. Depois fazemos um comparativo onde "S.Stock = T.Stock", esta é a ligação entre as chaves das duas tabelas.
Agora começam as comparações para estabelecermos a tomada de decisão. O primeiro comando "WHEN MATCHED AND (Qty + Delta = 0)" determina que se os registros existirem ambos na origem quanto no destino e a soma dos campos Qty e Delta for 0, o registro deve ser excluído, abaixo bem a instrução DELETE. Caso não atenda a esta condição vai para a próxima "WHEN MATCHED", ou seja, o registro foi encontrado, neste caso estamos fazendo um UPDATE. Caso não atenda nenhuma das duas primeiras, vamos para o próximo que é o "WHEN NOT MATCHED", ou seja, existe na origem mas não no destino. Neste caso faremos um INSERT.


Então, quando for utilizada a nova instrução MERGE, é possível fazer INSERT de dados, UPDATE ou DELETE, logicamente tendo como base este comparativo entre a tabela de origem e destino ou fontes de dados.

Até a Próxima

terça-feira, 29 de setembro de 2009

Criando Setup para Crystal Reports utilizando Merge Modules

Quando utilizamos os recursos do Crystal Reports no Visual Studio para desenhar nossos relatórios, precisamos ter a consciência de que haverá a necessidade da instalação dos componentes do Crystal no servidor onde a aplicação irá funcionar.

Nesta postagem eu explicarei como criar um Setup para Crystal utilizando Merge Modules.

Um Merge Module é um tipo especial de banco de dados Windows Installer que contém os componentes necessários para instalar um pacote de software pontual. Um Merge Module não pode ser instalado sozinho, mas deve ser fundido em uma instalação padrão do Windows Installer durante a criação da instalação. Normalmente, um Merge Module ou um conjunto de módulos de intercalação relacionados por dependências, instala um software ou parte de um produto durante a execução. O objetivo dos Merge Modules é permitir que você o adicione independente de módulos de software para múltiplas instalações.

Por exemplo, se há uma série de aplicações que requerem um componente especificamente configurada, seria possível criar um Merge Module que instala e configura o componente. Esse módulo de mesclagem poderia então ser adicionado aos pacotes de instalação de cada produto que exigia que determinado componente. Isso poupa o esforço de ter de adicionar individualmente os arquivos necessários, entradas do Registro, e outros componentes para cada instalação. Ele também poupa tempo se as atualizações são necessárias, pois em vez de atualizar as instalações para as cinco aplicações, apenas o Merge Module é atualizado, e o Setup só precisará ser recompilado.

Alguns Merge Modules podem ser configuráveis para mesclar módulos. Esses módulos de intercalação contém determinados valores que podem ser definidas para especificar como o módulo se comporta em sua instalação. Por exemplo, o autor do Merge Module pode permitir os atributos para serem definidos em componentes, habilitar ou desabilitar componentes isolados, especificar um bitmap para um diálogo, ou especificar como uma ação personalizada é executada. Os Merge Modules são suportados apenas pelo Windows Installer 2.0 ou superior.

Existem uma série de Merge Modules pré-criados para instalar pacotes de software Microsoft, como o MDAC, controles ActiveX MFC, SAPI, DCOM e o Crystal Reports que mostrarei agora.

Primeiro passo é baixar o Merge Module do Crystal Reports. Precisa ser verificada a versão do FrameWork que está sendo utilizada e fazer o download.

O Link a lista de Merge Modules disponíveis para Crystal Reports é:
http://wiki.sdn.sap.com/wiki/pages/viewpage.action?pageId=56787567

No caso deste exemplo, eu estou utilizando o seguinte:
CR 10.2 (VS .NET 2005)
CRRedist2005_x86.msm
WIN XP, WIN 2000, WIN 2003, WIN 7


Após baixar o Merge Modules, vamos montar o Projeto de Setup para Distribuição

1) Inicie o Visual Studio.
2) No Menu File, Selecione New Project.
3) Na Caixa de Diálogo “New Project”, Selecione Projeto Windows Setup ou Projeto Web Setup.



4) No “Solution Explorer”, selecione seu projeto, clique com o botão direito, e selecione Add Merge Module no Menu:
 



5) Adicione CrystalReportsRedist2005_x86.msm ao seu projeto:




Observe que Microsoft_VC80_ATL_x86.msm e policy_8_0_Microsoft_VC80_ATL_x86.msm serão incluídos automaticamente quanto você adicionar CrystalReportsRedist2005_x86.msm ao seu projeto:



6) Faça o Build do seu projeto.
7) Execute o Setup no servidor que hospedará as aplicações.

Como acabamos de ver, é muito simples a preparação do Setup para o Crystal, basta aplicar as dicas acima e testar a aplicação no servidor.

Até a próxima.

domingo, 27 de setembro de 2009

Configurando SQL Server para utilizar funções de Login do ASP.NET

Uma funcionalidade muito bacana do ASP.NET é o conjunto de controles de Login disponibilizados na caixa de ferramentas abaixo:



Utilizando este conjunto de controles é possível fazer login, exibir status do usuário, nome do usuário, criar usuário, mudar a senha, etc.



No ambiente de testes é possível fazer a configuração utilizando a ferramenta de configuração do ASP.NET (Menu Project -> ASP.NET Configuration).

Entretanto, para distribuir a aplicação é necessário alguns procedimentos para criação da base de dados e configuração da aplicação.

Primeiramente, o .Net Framework tem o seguinte comando para criação dos elementos da base de dados que deve ser executado no prompt de comando:

aspnet_regsql

Após execução do comando, abrirá um Wizard passo-a-passo conforme abaixo:






Este procedimento configura o conjunto de tabelas necessárias para armazenamento das informações de serviços de um aplicativo ASP.NET(associação, perfis, gerenciamento de funções, personalização e provendor de eventos da WEB do SQL). Esta configuração é válida apenas para SQL Server, uma vez que são criadas um conjunto de tabelas e procedures para prover toda a funcionalidade citada anteriormente.


Com esta configuração o banco de dados fica pronto para utilizar recursos muito valiosos do ASP.NET como Login, Gerenciamento de Usuários e Senhas, Roles, etc.
 
Abaixo um exemplo das tabelas e procedures que são criadas:
 





Com a base de dados configurada, basta configurar a aplicação para apontar para ela. Abaixo as modificações necessárias no arquivo Web.Config.


  



  
    
    
  
    


Com este recurso não é necessária a preocupação com controle de acessos, usuários, senhas, etc. O ASP.NET integra tudo no padrão muito fácil de ser utilizado pela aplicação.

Até a próxima.

quinta-feira, 24 de setembro de 2009

Coolite Toolkit, fazendo uma Web mais rica

Um dos maiores desafios da maioria dos programadores com certeza é a questão do designer da página. Como é difícil deixar a página com uma aparência agradável, sempre focamos mais para a funcionalidade e deixamos a outra parte para os Web Designers. Mas o que fazer quando não temos esse outro elemento na equipe?


Uma empresa chamada Coolite fez uma série de componentes para Visual Studio que são bastante interessantes tanto na aparência quanto na funcionalidade sendo 100% Ajax. Estes componentes deixam os Web Sites mais parecidos com o ambiente Desktop trazendo uma aparência e funcionalidade mais rica.

O Coolite instala todos os recursos disponíveis na barra de ferramentas:





Abaixo, alguns exemplos dos recursos disponíveis do Coolite:












São muitos recursos mesmo, vale a pena conferir. O link é http://examples.coolite.com/


O único problema do Coolite é que por ser uma ferramenta tão completa ela é paga, e não é barato.
O Site do Coolite é http://www.coolite.com/

Enfim, o CoolLite é mais uma ferramenta para nos ajudar no desenvolvimento de Web Sites com uma aparência mais rica e dependendo do projeto vale a pena pagar.

Gostaria de agradecer meu amigo Marcilio Rodrigues que me apresentou esta ferramenta.

quarta-feira, 23 de setembro de 2009

Controle para Gráficos em Asp.Net

Recentemente a Microsoft lançou um controle de Gráficos muito interessante para ser utilizado no Framework 3.5.

A partir de um simples controle com uma codificação muito fácil de implementar é possível criar gráficos que além de eficientes tem uma qualidade visual muito grande.







using System.Web.UI.DataVisualization.Charting;
...
private void Page_Load(object sender, System.EventArgs e)
{
    // Create new data series and set it's visual attributes
    Series series = new Series("Spline");
    series.ChartType = SeriesChartType.Spline;
    series.BorderWidth = 3;
    series.ShadowOffset = 2;

    // Populate new series with data
    series.Points.AddY(67);
    series.Points.AddY(57);
    series.Points.AddY(83);
    series.Points.AddY(23);
    series.Points.AddY(70);
    series.Points.AddY(60);
    series.Points.AddY(90);
    series.Points.AddY(20);

    // Add series into the chart's series collection
    Chart1.Series.Add(series);
}

Alguns exemplos dos tipos de gráfico que é possível gerar:




















E tem muito mais tipos de gráficos disponíveis, vale a pena conferir. O produto é muito bom e é oficial da Microsoft totalmente gratuito.


Isto deve prover uma útil adição para a sua caixa de ferramentas de funcionalidades da ASP.NET, permitindo que você facilmente adicione cenários de visualização e fluxo de dados mais elaborados em suas aplicações ASP.NET.


Para quem ficou interessado e quer instalar, seguem abaixo os links:


Nota: Sempre que for distribuir uma aplicação que utiliza os gráficos no ambiente de produção, deve ser instalado o Controle de Gráfico Microsoft neste servidor.

Aproveito para agradecer meu amigo Rodrigo Silva Souza que me sugeriu este Post.

terça-feira, 22 de setembro de 2009

Como enviar e-mails com C# de maneira síncrona e assíncrona

O e-mail é o mais popular mecanismo de comunicação onde aplicações modernas devem estar preparadas para poder trabalhar com este tipo de recurso.
O .Net Framework possui um conjunto de bibliotecas que facilitam muito nosso trabalho quando precisamos enviar mensagens desde as mais simples até as mais elaboradas contendo arquivos, relatórios, etc.

Agora vou mostrar como é fácil montar uma aplicação de envio de e-mails utilizando as bibliotecas System.NetSystem.Net.Mail.
 
O processo de criar e enviar um e-mail é o seguinte:
1. O primeiro passo é criar um objeto MailMessage que é o responsável por todos os atributos da mensagem que será enviada, como remetente, destinatário, cópias, anexos, assuntos, corpo, etc.
2. Para cada remetente, destinatário ou cópias podem ser criados objetos MailAddress ou simplesmente atribuir ao objeto MailMessage uma string contendo o e-mail diretamente.
3. Caso seja necessário anexar algum arquivo, este deverá ser atribuído ao objeto MailMessage através do método Attachments.Add.
4. Logo Após, criar o objeto SmtpClient que será responsável pela comunicação com o Servidor SMTP.
5. Se o servidor SMTP do remetente requer autenticação, deve-se criar as credenciais de acesso.
6. E por fim, basta passar o objeto MailMessage ao método Send do objeto SmtpClient.
 
Agora, vamos ver isso na prática

Criar o objeto MailMessage
MailMessage _mensagem = new MailMessage();

Atribuir o Remetente
_mensagem.From = new MailAddress("seuemail@dominio.com", "Nome Remetente");

Atribuir os destinatários
_mensagem.To.Add(new MailAddress("emaildestinatario@dominio.com"));

Pode atribuir também cópia e cópia oculta
_mensagem.CC.Add(new MailAddress("emaildestinatario@dominio.com"));
_mensagem.Bcc.Add(new MailAddress("emaildestinatario@dominio.com"));

Atribuir o assunto ao e-mail
_mensagem.Subject = "E-mail de Teste";

Definir se o corpo da mensagem será HTML. O padrão é falso.
_mensagem.IsBodyHtml = true;

Definir o corpo da mensagem
_mensagem.Body = "E-mail Teste";

Se houver anexos, pode atribuir também
_mensagem.Attachments.Add(new Attachment(@"C:\Boot.ini"));

Criar o objeto SmtpClient e atribuir as credenciais do remetente
SmtpClient _cliente = new SmtpClient("smtp.gmail.com");
_cliente.Credentials = new NetworkCredential("sua conta", "sua senha");

Habilitar criptografia HTTP utilizando SSL (Verificar se é requerido pelo provedor)
_cliente.EnableSsl = true;

E finalmente envia a mensagem
_cliente.Send(_mensagem);


O envio do e-mail é um processo que leva alguns segundos e dependendo do tamanho do anexo esse tempo aumenta. Dependendo da aplicação este tempo de espera pode comprometer o resultado. Para estes casos, a classe SmtpClient disponibiliza um método assíncrono para envio do e-mail.

Para esta implementação, a primeira coisa que deve ser feita é um tratamento para o evento SmtpClient.SendCompleted. Para poder responder a este evento basta implementar o método estabelecido no delegate. Este método só será chamado ao final do envio, liberando todos os recursos da aplicação enquanto executa a tarefa.

_cliente.SendCompleted += new SendCompletedEventHandler(sc_SendCompleted);
void sc_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
    if (e.Cancelled)
        Console.WriteLine("Mensagem cancelada");
    else if (e.Error != null)
        Console.WriteLine("Erro: " + e.Error.ToString());
    else
        Console.WriteLine("Mensagem enviada");
}

Agora basta finalizar o envio
_cliente.SendAsync(_mensagem, null);

Basicamente a diferença entre o envio síncrono e assíncrono é que no síncrono durante a execução da tarefa o sistema prende os recursos até que termine o envio, no assíncrono ele faz a solicitação, libera os recursos para continuar trabalhando e quando a tarefa terminar o sistema ativa o evento SendCompleted dando a opção de notificação para o usuário.
É realmente muito fácil trabalhar com envio de e-mails no .Net.

Abaixo o Link para Download do Exemplo utilizado para facilitar a compreensão.

Download do Exemplo

segunda-feira, 21 de setembro de 2009

A Importância da Certificação

Na área de informática há muitos profissionais com excelentes conhecimentos trabalhando com desenvolvimento de aplicações, infra, banco de dados, etc. Diferentemente de outras profissões como Advogado, Médico ou Engenheiro, na área de informática não há nenhuma entidade dedicada à fiscalização do exercício de nossa profissão. Isso é muito bom no primeiro momento quando ingressamos no mercado de trabalho, pois temos essa oportunidade de grande aprendizado e exercício da função antes mesmo de terminar o ensino superior. Realmente este tipo de regulamentação é algo tanto complicado dada a quantidade de cursos capacitadores que sempre estão surgindo. Vários profissionais já atuam no mercado de trabalho, destes uma grande parte atuam como consultores. Todos estes fatores aliados à enorme demanda de profissionais altamente dinâmicos que estejam constantemente atualizados com a tecnologia tornam esse mercado muito competitivo.

Nós desenvolvedores devemos nos conscientizar de um diferencial bastante interessante além da faculdade e pós-graduação que é a certificação. Para obter um destaque entre tantos profissionais, é muito importante que aproveitemos os conhecimentos e experiências adquiridos realizando exames que nos certificam através de uma entidade que reconhece toda a capacidade e especialidade na utilização de determinada ferramenta ou plataforma. No caso de desenvolvedores .Net, a Microsoft disponibiliza um conjunto de certificações organizadas em carreiras que é muito interessante e vale a pena correr atrás.

Quem quiser saber mais consulte o link:
http://www.microsoft.com/brasil/certifique/

Para o profissional que trabalha com desenvolvimento C#, a primeira certificação e base para todas as outras é a 70-536(.NET FRAMEWORK 2.0 APPLICATION DEVELOPEMENT FOUNDATION).

Esta prova aborda os aspectos gerais do .NET Framework 2.0 separados nos seguintes assuntos:
Framework Fundamentals
Input/Output (I/O)
Searching, Modifying, and Encoding Text
Collections and Generics
Serialization
Graphics
Threading
Application Domains and Services
Installing and Configuring Applications
Instrumentation
Application Security
User and Data Security
Interoperation
Reflection
Mail
Globalization

Esta prova é um pouco puxada dada a quantidade de assuntos, mas com uma boa experiência e uma boa dedicação nos estudos dá pra passar. É composta de 45 questões, o percentual que cai de cada assunto também pode ser obtido no link acima.

Quem estiver interessado, entre em contato comigo que eu tenho um material bacana para estudos.