ABC App – 04 Exceções

Ia deixar para escrever sobre o assunto depois, mas pra começar bem a semana vou usar o comentário do Tucaz e fazer um Refactoring no código e tratar Execeptions, ou Exceções!

exceção
ex.ce.ção
sf (lat exceptione) 1 Ato ou efeito de excetuar. 2 Desvio de regra, de lei, de princípio ou de ordem. 3 A coisa excetuada; aquilo que se desvia da regra. 4 Prerrogativa, privilégio. 5 Pessoa cujo modo de pensar ou de proceder se afasta do comum e usual. 6 Dir Alegação jurídica, constituindo defesa indireta (difere da contestação, que é defesa direta), pela qual o réu pretende baldar a ação intentada. E. declinatória, Dir: a que visa a declinar a competência do juiz ou tribunal ao qual foi apresentada a demanda. E. dilatória, Dir: a que pretende apenas demorar a demanda. E. peremptória, Dir: a que de todo e definitivamente afasta a demanda.

Conforme a definição acima do Michaelis, exceção é um desvio da regra. Na classe Customer da camada de DAL, quando fazemos acesso ao banco de dados para buscar um ou mais usuários, a EntLib abre uma conexão e executa o comando Select, essa é a regra, mas e quando o banco de dados não esta disponível? Ou se alguém renomeou ou apagou a tabela que esta na nossa query? Isso são exceções, e se não tratarmos, o sistema para de funcionar! Para testar é só desligar o banco de dados (parando o serviço SQL Server Browser) e rodar o nosso software.

Existem várias correntes de pensamento sobre Exceptions

Devemos tratar Exceptions como conexões a banco de dados, mas se um usuário do sistema cadastrar um número inválido de CPF devemos lançar uma Exeception? Devemos criar nossas próprias Execeptions para o nosso sistema? Onde devemos tratar? Muitas perguntas, algumas vão ficar sem respostas no momento, o objetivo desse post será fazer o Refactoring, e o primeiro será na conexão do banco.

Tratamento de Exceptions

No .Net é usado a tríade Try-Catch-Finally, o código passível de erro e que pode vir a lançar uma exceção é colocado no bloco do Try, no Catch é onde se pegam as execeções, e o Finally serve para finalizar alguma operação, limpar alguma variável,  e, muitas vezes,  ele não é usado, mas no nosso primeiro exemplo já faremos uso dele.
Uma regra que devemos sempre atentar é: nunca, NUNCA, colocar um método inteiro dentro de um bloco Try, não há necessidade de colocar criação de variáveis! Teste somente o que pode dar um erro. Além disso,  o código fica mais elegante.

No código da classe Customer da camada de DAL o que pode dar erro? O mais óbvio seria quando o DataReader estivesse sendo carregado, se nessa hora o banco de dados cair o nosso software vai pro espaço! Como no método AdaptToList ainda usamos o DataReader (ele fica aberto para popularmos o objeto Customer)  vamos colocar a linha de ExecuteReader e a de chamada do AdaptToLista dentro do Try. Para fazer isso,  vamos usar o recurso de Refactoring da IDE :  selecione as duas linhas, clique CTRL, e no menu de contexto escolha Surrond With…

Fazendo um Surrond With no código
Fazendo um Surrond With no código

Escolha a opção “tryf”, conforme figura abaixo, repare que este é um atalho para um Snippet, então quando estiver escrevendo código usando este atalho economiza tempo!

Escolha "tryf"
Escolha “tryf”

O código estará dentro do bloco Try, veja outras alterações no código abaixo e em seguida o por quê

[code lang=”csharp”]
public Domain.Customer GetCustomerById(int customerId)
{
IDataReader dr = null;
IList<Domain.Customer> lstCustomers = null;

string sql = “select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid”;

DbCommand cmd = db.GetSqlStringCommand(sql);

db.AddInParameter(cmd, “customerid”, DbType.Int32, customerId);

try
{
dr = db.ExecuteReader(cmd);
lstCustomers = AdaptToList(dr);
}
catch (System.Data.SqlClient.SqlException exsql)
{
throw new Exception(exsql.Message);
}
catch {
}

finally
{
if (!dr.IsClosed)
dr.Close();
}

return ((lstCustomers != null) || (lstCustomers[0] != null)) ? lstCustomers[0] : null;
}
}
[/code]

Listagem 01

Movi a declaração do DataReader para o início do método, pois podemos deixar dentro do Try, já que o Finally não iria enxergar esse objeto e depois é só mover a linha que faz a verificação se o DataReader estiver aberto para dentro do Finally, ocorrendo ou não um erro o Finally sempre é executado e daí ele ficará responsável por fechar o DataReader.
O Tucaz também fez um comentário sobre setar o CommandBehavior para CloseConnection, o que faria a conexão com o banco ser fechada após fecharmos o DataReader, mas a EntLib cuida disso pra gente! Veja o código fonte, e essa é a parte legal de usar essa biblioteca da MS, pois com o acesso ao fonte vemos as boas práticas sendo aplicadas, aquelas que se encontram no Guia de Acesso a Dados.
O Catch vazio vai pegar todo o tipo de exceção, então é bom especializarmos o Catch, por isso eu também coloquei para pegar a SQLException.

Aplique esse Refactoring no método GetCustomers() também.

OK… E vamos fazer isso também quando é criado o Database na classe BaseDAL, pois se o banco de dados estiver fora do ar vai dar um erro. É só executar os mesmos passos em cima da única linha que temos no único construtor da classe. E vai ficar assim:

[code lang=”csharp”]
public abstract class BaseDAL
{
public EntLib.Database db { get; set; }

public BaseDAL()
{
try
{
db = EntLib.DatabaseFactory.CreateDatabase(“Connection String”);
}
catch (Exception ex)
{
throw ex;
}
finally
{

}
}
}
[/code]

Listagem 02
E agora temos que exibir esses erros lá na nossa interface de usuário, aqui vai o código de como vai ficar:

[code lang=”csharp”]

namespace ABCApp.Console
{
class Program
{
static void Main(string[] args)
{

ABCApp.Domain.Customer c;

ABCApp.DAL.Customer dalCustomer = new ABCApp.DAL.Customer();

try
{
c = dalCustomer.GetCustomerById(1);
System.Console.WriteLine(c.CustomerId.ToString() + ” – ” + c.FirstName.ToString() + ” ” + c.LastName.ToString());
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
}

System.Console.ReadKey();

try
{
IList<Domain.Customer> lstCustomer = dalCustomer.GetCustomers();

foreach (Domain.Customer customer in lstCustomer)
{
System.Console.WriteLine(customer.CustomerId.ToString() + ” – ” + customer.FirstName.ToString() + ” ” + customer.LastName.ToString());
}
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
}

System.Console.ReadKey();
}
}
}
[/code]

Vamos testar? Para isso desligue o seu SQL Server! Vá no menu Iniciar > Microsoft SQL Server 2008 > Configuration Tools > SQL Server Configuration Manager, entre na ferramenta.  Pare o serviço SQL Server Browser, daí não deve ser possível conectar na base. Rodando a aplicação devem ser impressas mensagens de erro onde deveriam aparecer dados!

Bom… Isso foi só para começarmos a colocar um controle sobre os locais onde podem ocorrer Exceptions, esse não é o mundo perfeito, e nem será a última vez que irei falar sobre o tema. Mas por que não ler alguns links sobre isso? Aí vai:

http://unplugged.giggio.net/unplugged/post/Como-tratar-erros.aspx

http://msdn.microsoft.com/en-us/library/dd203116.aspx (Esse é sobre o bloco de Exceptions da EntLib, mais pra frente vamos usar ele)

http://www.developerfusion.com/article/5250/exceptions-and-performance-in-net/ (discute a questão de performance ao lançar exceções)

http://yoda.arachsys.com/csharp/exceptions2.html (também sobre performance)

http://www.artima.com/interfacedesign/AbnormalConditions.html

http://apparch.codeplex.com/ (aqui tem um vídeo sobre o tema)

Fico por aqui… Na quinta-feira post sobre objetos anêmicos…

O código deste post esta no Change Set 36605.

ABC App – 03 Fazendo um Refactoring na DAL

No post anterior,  iniciamos a contrução da ABC App, construindo uma camada de Domínio e uma camada de DAL. Antes de continuarmos a desenvolver, vamos aplicar um Refactoring?

Eu não gosto de termos em inglês para coisas que podemos falar em português, mas no caso do Refactoring eu abro uma exceção, normalmente o que se fala é Refatoração, mas essa palavra para mim é um termo matemático. O correto, IMHO, seria dizer Re-fabricar, mas fico com o termo em inglês.

E o que podemos fazer?

Vamos seguir usando Baby Steps, daqui por diante pequenos passos, ou seja , faço Refactoring e testo, Refactoring e testo, então não corro o risco de fazer uma grande alteração e me perder no código alterado e o sistema não funcionar. A primeira coisa para alterar é a criação da conexão com o BD, como será recorrente em toda classe DAL, podemos criar um classe base que todas dessa camada herdem e,  assim,  centralizarmos o código. Então,  primeira coisa, crie uma classe BaseDAL, como abaixo:

[code lang=”csharp”]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using System.Data.Common;
using System.Resources;
using EntLib = Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{

    public abstract class BaseDAL
    {
        public EntLib.Database db { get; set; }

        public BaseDAL()
        {
            db = EntLib.DatabaseFactory.CreateDatabase(&quot;Connection String&quot;);
        }
    }
}
[/code]

Listagem 01

A classe BaseDAL não poderá ser instanciada, só poderá ser herdada. Com isso, ganhamos um único ponto de conexão com o Banco de Dados, que será muito útil quando quisermos controlar um transação, outro ponto é no reuso de código. Para usarmos essa classe vamos herdar ela na classe Customer da DAL. Não se esqueça de apagar a linha indicada, pois agora usaremos o objeto Database da classe BaseDAL. Lembram-se do código abaixo?

[code lang=”csharp”]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Domain = ABCApp.Domain;

using System.Data;
using System.Data.Common;
using System.Resources;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{
    public class Customer : BaseDAL
    {
        public Domain.Customer GetCustomerById(int customerId)
        {
            //Apague a linha abaixo
//Database db = DatabaseFactory.CreateDatabase(&quot;Connection String&quot;);

            string sql = &quot;select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid&quot;;

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, &quot;customerid&quot;, DbType.Int32, customerId);

            IDataReader dr = db.ExecuteReader(cmd);

            Domain.Customer c = new Domain.Customer();

            while (dr.Read())
            {
                c.CompanyName = dr[&quot;companyname&quot;].ToString();
                c.CustomerId = Convert.ToInt32(dr[&quot;customerid&quot;]);
                c.EmailAddress = dr[&quot;emailaddress&quot;].ToString();
                c.FirstName = dr[&quot;firstname&quot;].ToString();
                c.LastName = dr[&quot;lastname&quot;].ToString();
                c.MiddleName = dr[&quot;middlename&quot;].ToString();
                c.ModifiedDate = Convert.ToDateTime(dr[&quot;modifieddate&quot;]);
                c.Phone = dr[&quot;phone&quot;].ToString();
            }

            if (!dr.IsClosed)
                dr.Close();

            return c;
        }
    }
}
[/code]

Listagem 02

Se já tivéssemos escrito mais classes DAL, o impacto dessa alteração seria muito maior. Então , seguindo nossso mantra de pequenos passos, vamos executar o código e saber se ele continua funcionando como o esperado.
Sendo o retorno igual ao que você tinha antes de modificar o código, então passamos neste Refactoring!
Vamos continuar implementando outros métodos na nossa classe DAL, o próximo interessante é retornar uma coleção de clientes. Podemos retornar todos os clientes e basicamente o método seria o mesmo do anterior mas sem o parâmetro de customerId e sem a linha de parâmetro no Command, vou criar então o método GetCustomers e que irá me retornar uma lista tipada de objetos, segue:

[code lang=”csharp”]
public IList&lt;Domain.Customer&gt; GetCustomers()
        {
            List&lt;Domain.Customer&gt; lstCustomers ;

            string sql = &quot;select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer&quot;;

            DbCommand cmd = db.GetSqlStringCommand(sql);

            IDataReader dr = db.ExecuteReader(cmd);

            lstCustomers = new List&lt;Domain.Customer&gt;();

            while (dr.Read())
            {
                Domain.Customer c = new Domain.Customer();

                c.CompanyName = dr[&quot;companyname&quot;].ToString();
                c.CustomerId = Convert.ToInt32(dr[&quot;customerid&quot;]);
                c.EmailAddress = dr[&quot;emailaddress&quot;].ToString();
                c.FirstName = dr[&quot;firstname&quot;].ToString();
                c.LastName = dr[&quot;lastname&quot;].ToString();
                c.MiddleName = dr[&quot;middlename&quot;].ToString();
                c.ModifiedDate = Convert.ToDateTime(dr[&quot;modifieddate&quot;]);
                c.Phone = dr[&quot;phone&quot;].ToString();

                lstCustomers.Add(c);
            }

            if (!dr.IsClosed)
                dr.Close();

            return lstCustomers;
        }
[/code]

Listagem 03

E para testar o código acima vamos escrever as seguintes linhas no nosso método Main no Projeto Console, logo abaixo da última linha já existente do nosso teste anterior:

[code lang=”csharp”]
            IList&lt;Domain.Customer&gt; lstCustomer = dalCustomer.GetCustomers();

            foreach (Domain.Customer customer in lstCustomer)
            {
                System.Console.WriteLine(customer.CustomerId.ToString() + &quot; – &quot; + customer.FirstName.ToString() + &quot; &quot; + customer.LastName.ToString());
            }

            System.Console.ReadKey();
[/code]

Listagem 04

O código acima chama o método da DAL e retorna uma coleção de Clientes. Se aparecerem  várias centenas de Clientes,  está certo!
O código escrito até agora. Será que é possível aplicar um Refactoring para melhorar algo? Bom, tem algo bem evidente, uma duplicação de código, os dois métodos fazem a leitura do DataReader e populam um objeto Customer, e um deles ele adiciona a uma lista de objetos já que o retorno são vários. Podemos centralizar esse código para que quando for preciso adicionar uma nova Propriedade a classe Customer seja preciso alterar somente em um lugar, então vou criar o método AdaptToList que irá receber um DataReader e retornar uma lista tipada de Customer:

[code lang=”csharp”]
public IList&lt;Domain.Customer&gt; AdaptToList(IDataReader dr)
        {

        }
[/code]

Listagem 05

O código da listagem 05 está praticamente pronto. Mova o código que se encontra na listagem 03, da linha 11 até 27 para dentro do método AdaptToList, e adicione a última linha, conforme a listagem 06! E repare que na inicialização da coleção Customer a declaração estava em outra linha,  então acrescente o tipo antes.

[code lang=”csharp”]
        public IList&lt;Domain.Customer&gt; AdaptToList(IDataReader dr)
        {
            List&lt;Domain.Customer&gt; lstCustomers = new List&lt;Domain.Customer&gt;();

            while (dr.Read())
            {
                Domain.Customer c = new Domain.Customer();

                c.CompanyName = dr[&quot;companyname&quot;].ToString();
                c.CustomerId = Convert.ToInt32(dr[&quot;customerid&quot;]);
                c.EmailAddress = dr[&quot;emailaddress&quot;].ToString();
                c.FirstName = dr[&quot;firstname&quot;].ToString();
                c.LastName = dr[&quot;lastname&quot;].ToString();
                c.MiddleName = dr[&quot;middlename&quot;].ToString();
                c.ModifiedDate = Convert.ToDateTime(dr[&quot;modifieddate&quot;]);
                c.Phone = dr[&quot;phone&quot;].ToString();

                lstCustomers.Add(c);
            }

            return lstCustomers;
        }
[/code]

Listagem 06

Para funcionar só é preciso chamar o método AdaptToList no método GetCustomers,  também alterei para que a lstCustomer fosse baseada em uma IList<T>, conforme a listagem abaixo:

[code lang=”csharp”]
        public IList&lt;Domain.Customer&gt; GetCustomers()
        {
            IList&lt;Domain.Customer&gt; lstCustomers = null; 

            string sql = &quot;select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer&quot;;

            DbCommand cmd = db.GetSqlStringCommand(sql);

            IDataReader dr = db.ExecuteReader(cmd);

            lstCustomers = AdaptToList(dr);

            if (!dr.IsClosed)
                dr.Close();

            return lstCustomers;
        }
[/code]

Listagem 07

Mais um pequeno passo, e mais um teste! Se rodou e continuou funcionando é por que o seu Refactoring foi bem feito! O que falta? Bem, se AdaptToList foi contruído para economizar código devemos usá-lo também no método GetCustomerById, mas nesse último método ele retorna apenas um Customer e não uma lista. Podemos então usar um artifício: pegar somente o primeiro item da lista para retornar, conforme listagem abaixo:

[code lang=”csharp”]
public Domain.Customer GetCustomerById(int customerId)
        {
            IList&lt;Domain.Customer&gt; lstCustomers = null;

            string sql = &quot;select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid&quot;;

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, &quot;customerid&quot;, DbType.Int32, customerId);

            IDataReader dr = db.ExecuteReader(cmd);

            lstCustomers = AdaptToList(dr);

            if (!dr.IsClosed)
                dr.Close();

          �
return ((lstCustomers != null) || (lstCustomers[0] != null)) ? lstCustomers[0] : null;
        }
[/code]

Listagem 08

Na listagem 08 está o método GetCustomerById como deve ficar, a mudança do List<Domain.Customer> para IList<Domain.Customer>, a chamada do método AdaptToList e o pulo do gato que é o uso do operador ternário para retornar somente o primeiro item da coleção, ou seja um objeto Customer, ou um null, não vamos discutir agora se retornar nulo é uma boa opção ou não!

Vou finalizar o post por aqui, para não ficar muito grande, resumindo o que fizemos aqui: Refactoring!
Melhoramos o nosso código, parece que não é necessário fazer isso agora, mas sempre que possível é interessante a fazer, no caso criamos uma classe para cuidar inicialmente da conexão com o banco de dados e como criamos outro método que populava a classe Customer criamos um método para cuidar especificamente disso.

O código deste post encontra-se no Change Set 35524, dúvidas e sugestões por favor comentem!

Referências:

Wikipedia Refatoração

Wikipedia Refactoring

Wikipedia Code Refactoring

ABC App – 02 Populando objetos sem uso de Dataset

Finalmente começando o código mesmo!

Objetivo: Popular um objeto simples com dados do banco sem fazer uso de Dataset

O que é necessário: Visual C# Express, MS SQL Express 2K8, banco de exemplo Adventure Works 2K8, MS Enterprise Library 4.1

Preparando o ambiente: Para quem nunca instalou o banco de exemplo Adventure Works, ele se encontra no CodePlex neste link aqui, mas tem uma pegadinha! Se não instalou o SQL Express Advanced, é um download maior, você não tem SQL Full Text Filter (veja se tem no Configuration Manager do SQL, é um serviço) e daí a instalação automática das bases de dados vai falhar, você terá que rodar os scripts manualmente, mas vai ter que alterar algumas variáveis. Então é melhor você ter a versão SQL Full Text Search, que está aqui. Usaremos somente o LT, que é mais enxuto em quantidade de tabelas, mas totalmente compatível com sua versão completa.
Quanto à MS Enterprise Library 4.1, ela é encontrada aqui, quando terminar o instalador vai perguntar se deseja compilar, responda Sim.

Pronto?

Se imaginarmos que estamos em um ambiente real de negócio nos já temos o BD, que é o Adventure Works, o que precisamos fazer é contruir uma classe de Customer (Cliente) que vai ser populada com os dados da tabela Customer do BD, dentro de um projeto Class Library que eu chamei de ABCApp.Domain:

[code lang=”csharp”]
namespace ABCApp.Domain
{
public class Customer
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string EmailAddress { get; set; }
public string Phone { get; set; }
public DateTime ModifiedDate { get; set; }
}
}
[/code]

Como o nosso objetivo aqui é não usar Dataset e também agora não iremos usar ORM (não sabe o que é? espere próximos posts), vamos usar ADO.Net, mas para facilitar as coisas vamos usar a MS Enterprise Library (que chamarei daqui em diante de EntLib). Vamos criar então um novo projeto que será a nossa DAL, Data Access Layer, camada de acesso a dados:

[code lang=”csharp”]
using ABCApp.Domain;

using Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{
public class Customer
{
public Customer GetCustomerById(int customerId){

}
}
}
[/code]

Repare que eu já adicionei duas referências, uma à EntLib, na janela Add Reference procure por Enterprise Library Data Access Application Block; e adicionei uma referência ao meu projeto ABCApp.Domain.
A primeira é para poder usar o bloco de acesso a dados da EntLib, e isso só vai ocorrer nesse projeto de DAL, que é minha camada de acesso a dados, a camada de Domain não vai saber onde os dados estão sendo persistidos!
E a segunda referência é porque o objeto que eu quero popular está na camada de domínio da aplicação.

Antes de continuarmos escrevendo a DAL, precisamos configurar como a EntLib irá fazer a conexão com o BD, e antes de fazermos isso precisamos adicionar um novo projeto a Solution, vamos adicionar um projeto do tipo Console para testarmos o código, por hora, por que existem maneiras melhores de fazer isso, mas não será feito nesse post. A Solution deverá ficar assim:

A Solution deverá estar parecida com essa figura
A Solution deverá estar parecida com essa figura

Insira um arquivo do tipo App.config no novo projeto, é nele que iremos configurar a conexão com o BD, e para isso existe uma ferramente que é integrada ao VS.Net no momento da instalação da EntLib, mas como estou fazendo na versão Express vamos usar a ferramenta externa que também é instalada, procure no menu Inicar: Microsoft Patterns & Practices > Enterprise Library 4.1 – October 2008 > Enterprise Library Configuration, e você terá a seguinte tela:

EntLibConfiguration

Quando abrir a janela, vá em File > Open, e procure pelo arquivo App.config criado no projeto Console. Na pasta Connection String você pode criar várias conexões, mas no momento só precisamos de uma, apague as outras e crie uma nova, do lado direito da tela em General > ConnectionString preencha com as informações de localização do SQL Express, BD, senha, … o padrão. Salve o arquivo, feche, e ao voltar ao VS.Net Express ele vai pedir para recarregar o arquivo App.config, se ele ficou aberto.

Agora finalmente vamos codificar o acesso ao BD, segue abaixo.

[code lang=”csharp”]
using Domain = ABCApp.Domain;

using System.Data;
using System.Data.Common;
using System.Resources;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{
public class Customer
{
public Domain.Customer GetCustomerById(int customerId)
{ �
Database db = DatabaseFactory.CreateDatabase(“Connection String”);

string sql = “select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid”;

DbCommand cmd = db.GetSqlStringCommand(sql);

db.AddInParameter(cmd, “customerid”, DbType.Int32, customerId);

IDataReader dr = db.ExecuteReader(cmd);

Domain.Customer c = new Domain.Customer();

while (dr.Read())
{
c.CompanyName = dr[“companyname”].ToString();
c.CustomerId = Convert.ToInt32(dr[“customerid”]);
c.EmailAddress = dr[“emailaddress”].ToString();
c.FirstName = dr[“firstname”].ToString();
c.LastName = dr[“lastname”].ToString();
c.MiddleName = dr[“middlename”].ToString();
c.ModifiedDate = Convert.ToDateTime(dr[“modifieddate”]);
c.Phone = dr[“phone”].ToString();
}

if (!dr.IsClosed)
dr.Close();

return c;
}
}
}

[/code]

Explicando o código acima

Primeiramente repare nos Using, eu acrescentei uma referência ao projeto ABCApp.Domain, pois é lá que esta a classe que eu quero popular; e ao System.Data e System.Data.Common, pois vou usar o objeto Command e o DataReader do ADO.Net.
Na linha 14 eu estou criando o “BD”, essa DatabaseFactory vai criar automáticamente uma Connection para mim, através da minha ConnectionString configurada, e através desse objeto vamos interagir com o BD. A vantagem é que a EntLib vai cuidar da conexão para a gente, abrir, fechar, e outras coisas!
O objeto Command já é conhecido de quem já programou com ADO.Net, o legal aqui é que na linha 20 é criado um objeto de parâmetro, normalmente se concatenaria o código na string mas não é uma prática muito recomendada.
A grande diferença aqui é o uso do Data Reader, como não estamos usando um DataSet, vamos puxar os dados do BD e popular um objeto, que é feito na linha 22, então é só ler o objeto dr e ir populando os dados depois de inicializado o nosso objeto de Domain.

Para testar é só escrever o código abaixo no Main do nosso projeto Console.

[code lang=”csharp”]
static void Main(string[] args)
{

ABCApp.Domain.Customer c;

ABCApp.DAL.Customer dalCustomer = new ABCApp.DAL.Customer();

c = dalCustomer.GetCustomerById(1);

System.Console.WriteLine(c.CustomerId.ToString() + ” – ” + c.FirstName.ToString() + ” ” + c.LastName.ToString());

System.Console.ReadKey();
}
[/code]

Qual a vantagem de usarmos isso tudo?

Bom, primeiramente estamos programando realmente em OO, temos um objeto de domínio, a camada de acesso a dados esta isolada do resto, e principalmente não estamos usando DataSet!

Se você quiser baixar o código esta disponível no CodePlex – ABCApp e baixe o Change Set – 33351.

No próximo post (assine o feed para acompanhar) vou mostrar o que podemos fazer de interessante tendo esse objeto de domínio e vou fazer um Refactoring para darmos uma melhorada no código já, pois a idéia aqui era mostrar mais o acesso através da EntLib e como fazer sem o uso de DataSet. Até lá!
Críticas, sugestões, dúvidas são sempre bem-vindas, use o recurso de comentário do blog, a sua dúvida pode ser a de outro, e fica disponível para todos!

ABC App – 01

Ano passado comecei um projeto no CodePlex para mostrar o padrão MVC em Windows Forms para quem ainda não conhece. Mas o projeto ficou parado, mudei de .Net 2005 para .Net 2008 e o projeto não andou, esse ficou pesado, mas acho que é hora de começar me mexer!

Resolvi que não vou focar em MVC, vou usar o projeto para escrever sobre boas práticas, coisas que uso no meu dia- a-dia, então mudei o nome dele novamente (hehe) e ficou assim: ABC App.

Aqui no blog vou usar a categoria abcapp para publicar os posts referentes a essa série.

O código fonte deste projeto está hospedado no CodePlex em ABCApp, e , como o projeto é para quem também está iniciando então vou usar as ferramentas Express da Microsoft, Visual C# Express 2008. Vou usar também o TortoiseSVN, é só baixar o arquivo MSI e instalar. Antes , para acessar o CodePlex usando o TortoiseSVN era necessário o uso do  SvnBridge, desenvolvido pela equipe do site, agora não é mais necessário. Todo o projeto tem uma URL para ele, do ABCApp é https://abcapp.svn.codeplex.com/svn.

Eu criei o projeto na pasta Projects que o VS.Net cria dentro da pasta Documentos do Usuário.

Depois que você instalou o TortoiseSVN é possível baixar em qualquer lugar o projeto, basta clicar com o botão direito do mouse dentro de uma pasta vazia, e escolher a opção “SVN Checkout” do menu de contexto.

Conforme o projeto for evoluindo é só atualizar o fonte, para isso clique com o botão direito do mouse dentro da pasta e escolha “SVN Update”.

Quem tem uma licença do VS.Net, pode baixar aqui o Team Explorer, ele não vai funcionar com as versões Express, infelizmente!

Para quem quer saber mais sobre o Subversion e Tortoise , saiu uma matéria na edição 07 de Fevereiro/Março da Mundo.Net, e aqui você pode baixar um livro sobre o Subversion.

Próximo post vou começar a desenvolver o aplicativo e vou começar a falar de uma maneira de desenvolver usando objetos de negócio acessando o banco de dados sem o uso de Dataset’s!