Buscar

Programação Orientada a Objetos C# - USANDO PADRÕES DE PROJETO

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 3, do total de 20 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 6, do total de 20 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 9, do total de 20 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Prévia do material em texto

POO 
Programação Orientada a 
Objetos no C# .NET usando 
Padrões de Projeto 
MARCELO SANTOS DAIBERT E MARCO ANTÔNIO PEREIRA ARAÚJO 
 
 
Marcelo Santos Daibert (marcelo@daibert.net) é professor do Curso de Bacharelado em Ciência 
da Computação da FAGOC - Faculdade Governador Ozanam Coelho na graduação e pós-
graduação (especialização), Mestrando e Especialista em Ciência da Computação pela 
Universidade Federal de Viçosa e Bacharel em Sistemas de Informação pela Faculdade Metodista 
Granbery. Gerente técnico da Optical Soluções em Informática. 
 
 
Marco Antônio Pereira Araújo (maraujo@granbery.edu.br) é professor do Curso de Bacharelado 
em Sistemas de Informação da Faculdade Metodista Granbery, Doutorando e Mestre em 
Engenharia de Sistemas e Computação pela COPPE/UFRJ, Especialista em Métodos Estatísticos 
Computacionais e Bacharel em Informática pela UFJF, Analista de Sistemas da Prefeitura de Juiz 
de Fora. 
 
Este artigo discute Este artigo usa as seguintes tecnologias 
• Orientação a Objetos; 
• Padrões de Projeto; 
• Mapeamento Objeto-Relacional; 
• Criação de classes; 
• Programação em camadas; 
• Persistência de objetos. 
Visual Studio 2008, C#, SQL Server 2005. 
 
Com o passar dos anos foi possível observar uma profunda evolução na utilização de 
computadores. Hoje graças a esta evolução, juntamente com fenômenos como a globalização, é 
possível estar em sincronia com as notícias de todas as partes do mundo. Nunca se utilizou tanto 
quanto atualmente recursos computacionais, firmando assim esta tecnologia como necessária para a 
vida moderna atual. Neste sentido, várias evoluções foram necessárias para se alcançar o atual 
patamar e novas outras evoluções se fazem necessárias para alcançar novos patamares que se 
reservam no futuro. 
Na área da engenharia de software não foi diferente. O desenvolvimento de software se 
amadureceu e ainda deve amadurecer com o passar dos anos. Para autores da área, fatores chaves 
para que houvesse mudanças e evolução no desenvolvimento de software nos últimos anos são: 
 
 
mudanças na economia, interface com o usuário, operações em rede, tempo de disponibilização para 
o mercado (time to market - TTM), problemas com o modelo em cascata, tecnologia de objetos (OO 
– Orientação a Objetos) e computação em desktops. 
A qualidade de software passou a ser um tema muito discutido. O foco para a qualidade dos 
sistemas desenvolvidos dentro de uma organização ganhou papel principal entre as discussões dos 
engenheiros. Assim, várias são as abordagens de desenvolvimento que buscam garantir esta 
qualidade. 
Neste contexto, o C# é uma linguagem de programação que une o poder e a flexibilidade da 
linguagem C/C++ com a produtividade de linguagens e ambientes de desenvolvimento rápido 
(RAD - Rapid Application Development). Quando aplicadas técnicas da programação orientada a 
objetos, com padrões de desenvolvimento de software, a linguagem se mostra uma poderosa 
ferramenta para desenvolvimento de software, com suporte as mais novas tecnologias do mercado. 
Este artigo tem o objetivo de abordar de forma prática o desenvolvimento de uma aplicação, 
usando a linguagem C# do Visual Studio .NET 2008, utilizando os recursos da Programação 
Orientada a Objetos (POO), do .NET, contextualizando a utilização de alguns padrões de projeto, 
em especial o padrão DAO (Data Access Object) para persistência e manipulação dos objetos da 
aplicação. Para armazenar os dados da aplicação desenvolvida é utilizado o banco de dados MS-
SQL Server 2005. Toda a aplicação é desenvolvida com o conceito de programação em camadas, 
também discutido no artigo. 
Um dos desafios no desenvolvimento de aplicações orientadas a objetos é a persistência de 
objetos. Os bancos de dados puramente orientados a objetos são de fato os mais adequados para a 
persistência, mas a indisponibilidade atual desses, seja devido ao custo, diversidade e 
principalmente amadurecimento, faz com que seja necessária uma busca por alternativas para a 
realização dessa tarefa. 
Uma das soluções encontradas para o problema é a utilização de camadas de persistência para 
a manipulação dos objetos utilizando bancos de dados relacionais. Essa abordagem vem sendo 
amplamente utilizada no mercado, principalmente para o desenvolvimento de sistemas de médio a 
grande porte. 
Basicamente une a rapidez e o amadurecimento das bases de dados relacionais com os 
benefícios da programação orientada a objetos (POO). A função principal de uma camada de 
persistência é portal transparentemente os objetos de uma aplicação para a base de dados relacional 
de forma genérica. 
Para isso, são utilizas principalmente técnicas de mapeamento objeto-relacional com o intuito 
de mapear as classes e associações para tabelas e relacionamentos. A utilização de uma camada de 
persistência, embora pareça trivial inicialmente, se mostra complexa na prática, uma vez que são 
várias as configurações que devem ser feitas para que a camada funcione corretamente, além de 
outros fatores que dificultam sua utilização. A edição 34 da revista .NET Magazine, antes chamada 
de MSDN Magazine, foi dedicada a esta abordagem, onde o estudo de caso apresentou a utilização 
de um framework de persistência chamado nHibernate. 
Utilizando esse mesmo raciocínio, outra solução, a abordada neste artigo, apresenta o mesmo 
estudo de caso apresentado na edição 34, mas com uma diferença: A própria aplicação faz o 
mapeamento objeto-relacional e a conexão com o banco de dados. Para isso, é apresentado o padrão 
de projeto DAO, que se apresenta como outra camada do sistema, com a responsabilidade de 
conectar no banco de dados, persistir e manipular os objetos da aplicação. 
 
Padrões de Projeto (Design Patterns): são soluções elegantes e reutilizáveis para problemas 
recorrentes do processo de desenvolvimento de software Orientado a Objetos. 
 
Estudo de Caso 
Como já apresentado, o estudo de caso deste artigo é o mesmo apresentado na edição 34 desta 
revista, mas com a diferença de utilizar outra abordagem na persistência de objetos. O estudo de 
 
 
caso apresenta um fragmento de um sistema maior, representado aqui pela relação entre 
funcionários e departamentos de uma empresa, através das classes Departamento, Funcionario e 
FuncionarioHorista. A classe Funcionario é abstrata, servindo para a definição dos elementos 
comuns às suas subclasses através da herança. 
Todos os funcionários devem estar lotados em um Departamento, que pode ter vários 
funcionários. A Figura 1 representa o diagrama de classes do nosso sistema. 
 
FuncionarioHorista
numDiasTrabalhados : int
numHorasDiaTrabalhado : int
valorHora : int
Departamento
codigo : String
Descricao : String
Funcionario
codigo : String
nome : String
cpf : String
calcularSalario : float()
1
0..*
1
0..*
 
Figura 1. Diagrama de Classes do estudo de caso. 
 
Através desse estudo de caso, são abordados temas como classes, objetos, métodos, atributos, 
persistência de objetos, herança, polimorfismo, herança, diálogos, associações e programação em 
camadas MVC (Model-View-Controller), além de temas pertinentes ao ambiente de 
desenvolvimento, como utilização de componentes, classes e controles disponibilizados pelo Visual 
Studio 2008 e o framework .NET. 
O estudo de caso propõe o desenvolvimento em camadas, utilizando o padrão de projeto 
estrutura MVC, composto por três camadas fundamentais. Esta abordagem busca, entre outras 
coisas, o desacoplamento de funções da aplicação, facilitando assim o desenvolvimento e 
garantindo maior manutenibilidade da aplicação. Além das três camadas do MVC, é ainda 
apresentada uma outra camada, a responsável pela persistência dos dados. Esta camada, aqui 
chamada de camada de persistência tem a responsabilidade de comunicar com o banco de dados e 
de persistir e manipular os objetos nestebanco. A Figura 2, representa as camadas do estudo de 
caso e como é feita a comunicação entre elas. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Classes de Interface com usuário (View) 
Classes de Controle (Controller) 
Classes de Negócio (Model)  
Banco de 
Dados 
SQL 
Camada de Persistência (Classes DAO)
Modelo 
MVC 
 
 
 
Figura 2. Camadas do Estudo de caso. 
 
No contexto do estudo de caso, o View é representado pelas classes de interface com o 
usuário. Estas se comunicam com os controladores de das classes de domínio. As classes 
controladoras (Controller) têm a finalidade de ser um elo entre o Model e o View, ou seja, entre as 
classes de domínio da aplicação e a interface, garantindo assim o desacoplamento. Já o Model é 
representado pelas classes de domínio, e que neste estudo de caso são as classes Funcionario, 
FuncionarioHorista e Departamento. O Model faz acesso às classes de persistência DAO para 
persistir e manipular os seus objetos. E esta, por sua vez, faz acesso ao banco de dados e 
efetivamente faz a tarefa de persistir e manipular os objetos. 
 
 
Classes do Modelo, Propriedades e Métodos 
Para iniciar o desenvolvimento do estudo de caso, foi criado um projeto no Visual Studio 
chamado Empresa. Este projeto será divido em cinco namespaces, como pode ser visualizado na 
Figura 3. O namespace View, para armazenar as classes de interface, o Controller, para as classes 
controladoras, o Model, para as classes de domínio, o Persistence para as classes DAO de acesso ao 
banco de dados e por fim, o namespace Resources, para armazenar as imagens utilizadas nas 
interfaces. 
 
 
Figura 3. Namespaces do projeto do estudo de caso. 
 
As listagens 1, 2 e 3 apresentam o código-fonte de definição das classes Funcionario, 
FuncionarioHorista e Departamento, respectivamente, do estudo de caso proposto, todas dispostas 
no namespace Model e com os nomes: Funcionario.cs, FuncionarioHorista.cs e Departamento.cs. 
 
Listagem 1. Definição da Classe Funcionario 
1. using System; 
2. using System.Collections.Generic; 
3. using System.Collections; 
4. using System.Text; 
5. using Empresa.Persistence; 
6. 
7. namespace Empresa.Model{ 
8. public abstract class Funcionario{ 
9. public Funcionario(String pNome, String pCPF){ 
10. this.Nome = pNome; 
11. this.CPF = pCPF; 
12. this.Departamento = new Departamento(); 
13. } 
14. public Funcionario(){ 
15. } 
16. 
17. private String codigo; 
 
 
18. private String nome; 
19. private String cpf; 
20. private Departamento departamento; 
21. 
22. public String Codigo{ 
23. get { return this.codigo; } 
24. set { this.codigo = value; } 
25. } 
26. public String Nome{ 
27. get { return this.nome; } 
28. set { this.nome = value; } 
29. } 
30. public String CPF{ 
31. get { return this.cpf; } 
32. set { this.cpf = value; } 
33. } 
34. public Departamento Departamento{ 
35. get { return this.departamento; } 
36. set { this.departamento = value; } 
37. } 
38. public abstract float calcularSalario(); 
39. public abstract Boolean Persistir(); 
40. public abstract Boolean Atualizar(); 
41. public static Funcionario RecuperaObjeto(String pID){ 
42. Funcionario objFuncionario = FuncionarioDAO.recuperaObjeto(pID); 
43. return objFuncionario; 
44. } 
45. public static IList RecuperaObjetos(){ 
46. IList listFuncionarios = FuncionarioDAO.recuperaObjetos(); 
47. return listFuncionarios; 
48. } 
49. public static IList RecuperaObjetosPorDepartamento(String pOID){ 
50. IList listFuncionarios = 
FuncionarioDAO.recuperaObjetosPorDepartamento(pOID); 
51. return listFuncionarios; 
52. } 
53. public static Boolean Excluir(String pID){ 
54. return FuncionarioDAO.excluir(pID); 
55. } 
56. } 
57. } 
 
 
Na Listagem 1, a linha 8 exibe a assinatura da classe abstrata Funcionario. Ela é abstrata por 
não instanciar objetos, tendo por objetivo definir os elementos comuns às suas subclasses. Entre as 
linhas 17 e 20 são apresentados os atributos codigo, nome, cpf e departamento da classe. Todos com 
visibilidade privada, sendo acessados pelas propriedades definidas entre as linhas 22 e 37. As 
propriedades, nesse caso, agem como métodos gets e sets, mantendo, portanto, o encapsulamento da 
classe. 
 
Nota: Encapsulamento é a prática de limitar o acesso às informações de um objeto, fazendo 
com que somente os seus métodos tenham acesso aos dados e à manipulação dos atributos. O 
encapsulamento disponibiliza o objeto com toda sua funcionalidade sem a necessidade de saber 
internamente o funcionamento, aumentando assim a manutenibilidade do sistema. 
 
Das linhas 9 a 15 são apresentados os métodos construtores da classe, onde temos dois: um 
com passagem de parâmetros dos atributos na sua construção e outro sobrecarregando o anterior 
sem parâmetros, usado para instanciar um objeto sem informações para seus atributos. O método 
sobrecarregado (overload) é definido quando a assinatura do mesmo, difere do anterior na passagem 
de parâmetros. Uma classe pode ter quantos métodos sobrecarregados forem necessários. 
Na linha 38 é exibido a assinatura do método abstrato calcularSalario. Ele é abstrato, pois é 
redefinido nas subclasses, de acordo com a necessidade específica de implementação. A isso é dado 
 
 
o nome de polimorfismo, que é a capacidade de um método de mesma assinatura comportar-se de 
maneira diferente, em uma mesma hierarquia. 
Exemplificando o uso, o método calcularSalario possui a mesma assinatura em toda a 
hierarquia, no entanto, ele se comporta de maneira diferente na subclasse FuncionaoHorista, uma 
vez que o algoritmo para calcular salário é diferente nessa subclasse. O fato do método ser definido 
como abstrato (abstract) em sua assinatura, obriga suas subclasses a implementá-lo. 
Entre as linhas 39 e 55 são definidos os métodos responsáveis pela persistência e manipulação 
dos objetos do tipo Funcionario. Observe que todos esses métodos fazem acesso às classes DAO, 
que é importado para a classe pela linha 5 (using Empresa.Persistence). Como já apresentado, as 
classes DAO são as responsáveis pela conexão com o banco de dados e pela persistência e 
manipulação dos objetos. De acordo com a programação em camadas, estes métodos serão 
chamados pelos controladores da classe para finalmente, a classe fazer as chamadas para as classes 
DAO como apresentado acima. 
Observe que são definidos algum métodos com o modificador static, como por exemplo, na 
linha 45. Este indica que o método é um método de classe e não é necessário instanciar objeto para 
que o mesmo seja invocado. 
 
Nota: Método de Classe é um método que não há a necessidade se instanciar um objeto da 
classe para poder acessá-lo. Diferentemente do método de instância, que como o próprio nome diz, 
é necessário a instanciação do objeto para sua invocação. 
 
 
Listagem 2. Definição da Classe FuncionarioHorista 
1. using System; 
2. using System.Collections.Generic; 
3. using System.Collections; 
4. using System.Text; 
5. using Empresa.Persistence; 
6. 
7. namespace Empresa.Model{ 
8. class FuncionarioHorista : Funcionario{ 
9. public FuncionarioHorista(String pNome, String pCPF, int pValorHora, int 
pNumDiasTrabalhado, int pNumHorasTrabalhada) 
10. : base(pNome, pCPF){ 
11. this.valorHora = pValorHora; 
12. this.numHorasDiaTrabalhado = pNumHorasTrabalhada; 
13. this.numDiasTrabalhados= pNumDiasTrabalhado; 
14. } 
15. public FuncionarioHorista(){ 
16. } 
17. 
18. private int numDiasTrabalhados; 
19. private int numHorasDiaTrabalhado; 
20. private int valorHora; 
21. 
22. public int NumDiasTrabalhados{ 
23. get { return this.numDiasTrabalhados; } 
24. set { this.numDiasTrabalhados = value; } 
25. } 
26. public int NumHorasDiaTrabalhado{ 
27. get { return this.numHorasDiaTrabalhado; } 
28. set { this.numHorasDiaTrabalhado = value; } 
29. } 
30. public int ValorHora{ 
31. get { return this.valorHora; } 
32. set { this.valorHora = value; } 
33. } 
34. 
35. public override float calcularSalario(){ 
36. return this.valorHora * this.numHorasDiaTrabalhado * 
this.numDiasTrabalhados; 
37. } 
 
 
38. public override Boolean Persistir(){ 
39. FuncionarioHoristaDAO objFunHoristaDAO = new FuncionarioHoristaDAO(); 
40. if (objFunHoristaDAO.persistir(this)){ 
41. return true; 
42. }else{ 
43. return false; 
44. } 
45. } 
46. public override Boolean Atualizar(){ 
47. FuncionarioHoristaDAO objFunHoristaDAO = new FuncionarioHoristaDAO(); 
48. if (objFunHoristaDAO.atualizar(this)) 
49. { 
50. return true; 
51. } 
52. else 
53. { 
54. return false; 
55. } 
56. } 
57. } 
58. } 
 
Já na Listagem 2, é definida a classe FuncionarioHorista, com seus atributos, propriedades e 
métodos. Importante observar nas linhas 8 e 16, no método construtor da classe, a utilização da 
palavra reservada base. Essa é utilizada para invocar o método construtor do pai, passando os 
parâmetros referentes à super classe. 
Deve sempre suceder a assinatura do método separado por dois pontos. Lembrando que a 
ordem dos parâmetros deve ser a mesma da assinatura, assim como em qualquer chamada de 
método. A linha 35 apresenta a definição do método calcularSalario. Como esse método remete ao 
método abstrato do pai, o mesmo deve ser definido como override. Esse sim com implementação 
em sua definição. 
 
 
Listagem 3. Definição da Classe Departamento 
1. using System; 
2. using System.Collections.Generic; 
3. using System.Collections; 
4. using System.Text; 
5. using System.Windows.Forms; 
6. using Empresa.Persistence; 
7. 
8. namespace Empresa.Model{ 
9. public class Departamento{ 
10. public Departamento(){ 
11. } 
12. 
13. private String codigo; 
14. private String descricao; 
15. 
16. public String Codigo{ 
17. get { return this.codigo; } 
18. set { this.codigo = value; } 
19. } 
20. public String Descricao{ 
21. get { return this.descricao; } 
22. set { this.descricao = value; } 
23. } 
24. public Boolean Persistir(){ 
25. DepartamentoDAO objDepartamentoDAO = new DepartamentoDAO(); 
26. if (objDepartamentoDAO.persistir(this)){ 
27. return true; 
28. }else{ 
29. return false; 
30. } 
31. } 
32. public Boolean Atualizar(){ 
 
 
33. DepartamentoDAO objDepartamentoDAO = new DepartamentoDAO(); 
34. if (objDepartamentoDAO.atualizar(this)){ 
35. return true; 
36. } 
37. else{ 
38. return false; 
39. } 
40. } 
41. public static Departamento RecuperaObjeto(String pID){ 
42. Departamento objDepartamento = DepartamentoDAO.recuperaObjeto(pID); 
43. return objDepartamento; 
44. } 
45. public static IList RecuperaObjetos(){ 
46. IList listDepartamentos = DepartamentoDAO.recuperaObjetos(); 
47. return listDepartamentos; 
48. } 
49. public static Boolean Excluir(String pID){ 
50. return DepartamentoDAO.excluir(pID); 
51. } 
52. } 
53. } 
 
 
Por fim, na Listagem 3 é apresentada a classe Departamento, com seus atributos, 
propriedades e métodos. Na linha 10 é exibido o método construtor do objeto. Entre as linhas 13 e 
23 são exibidos os atributos e propriedades da classe. 
Nas classes apresentadas nas listagens anteriores são definidos os métodos Persistir (persiste 
um objeto), Atualizar (atualiza um objeto já persistido), RecuperaObjeto (recupera um único objeto 
especificado), RecuperaObjetos (recupera todos os objetos da classe referenciada) e Excluir (exclui 
um objeto especificado). Esses são os métodos responsáveis pela persistência e manipulação dos 
objetos no sistema. Observe que todos fazem acesso às classes DAO, do namespace Persistence. A 
classe Funcionario possui ainda o método RecuperaObjetosPorDepartamento. Este método 
recupera todos os funcionários de um determinado departamento especificado. 
 
Classes de Interface e Controladores 
Dentro do namespace View estão dispostas as classes com as interfaces, como visualizado na 
Figura 4. São definidas as seguintes interfaces: frmPrincipal (a interface principal do sistema, 
apresentada na Figura 5), frmSplashScreen (com a interface de inicialização da aplicação), frmSobre 
(interface sobre do sistema), frmListarTemplate (define um template para reutilização de interfaces, 
baseando-se no conceito de herança de interfaces), frmListarFuncionario (herda de 
frmListarTemplate e apresenta a interface de visualização de todos os funcionários), 
frmListarDepartamento (também herda de frmListarTemplate e apresenta a interface de 
visualização de todos os departamentos), frmNovoFuncionarioTemplate (define o template para a 
interface de novos funcionários), frmNovoFuncionarioHorista (interface para criar um novo 
funcionário horista), frmNovoDepartamento (interface para criar um novo departamento no 
sistema), e por fim a interface frmFuncionariosDepartamento (lista todos os funcionários de um 
determinado departamento). 
 
 
 
 
Figura 4. Classes de Interface. 
 
 
 
Figura 5. Interface Principal do Sistema - frmPrincipal. 
 
As classes de interface definem as interfaces da aplicação (View). Estas, por sua vez, fazem 
acesso às classes controladoras (Controller), que então fazem acesso às classes do modelo (Model), 
já definidas. E as classes do modelo fazem acesso às classes de persistência DAO (Persistence 
DAO). 
As classes controladoras são definidas dentro do namespace Controller. As Listagens 4 e 5 
apresentam respectivamente os controladores cntrFuncionario e cntrFuncionarioHorista. Todos 
possuem a mesma funcionalidade: elo de ligação entre o model e o view. A estrutura também é 
muito semelhante em todas essas classes. Elas basicamente possuem um atributo do tipo da classe 
que gerenciam, menos para a cntrFuncionario, já que esta gerencia uma classe abstrata. Os métodos 
também possuem a mesma estrutura e todos fazem acesso ao modelo. Basicamente existe o método 
Salvar, responsável por persistir ou atualizar um objeto, o método RecuperaObjeto, para recuperar 
um determinado objeto, o RecuperaObjetos, para recuperar todos os objetos da classe persistidos e 
o método Excluir, responsável por excluir um determinado objeto. 
 
Listagem 4. Definição da Classe cntrFuncionario 
1. using System; 
2. using System.Collections.Generic; 
3. using System.Collections; 
4. using System.Text; 
5. using Empresa.Model; 
6. using Empresa.Persistence; 
7. 
8. namespace Empresa.Controller{ 
 
 
9. class cntrFuncionario{ 
10. public cntrFuncionario(){ 
11. } 
12.public static ArrayList RecuperaObjetos(){ 
13. ArrayList vetEnviaFuncionarios = new ArrayList(); 
14. IList listFuncionarios = Funcionario.RecuperaObjetos(); 
15. for (int i = 0; i < listFuncionarios.Count; i++) 
16. { 
17. Funcionario objBuffer = (Funcionario)listFuncionarios[i]; 
18. String[] vBuffer = new String[4]; 
19. vBuffer[0] = objBuffer.Codigo; 
20. vBuffer[1] = objBuffer.Nome; 
21. vBuffer[3] = objBuffer.Departamento.Descricao; 
22. if (objBuffer is FuncionarioHorista) 
23. { 
24. vBuffer[2] = "Horista"; 
25. } 
26. vetEnviaFuncionarios.Add(vBuffer); 
27. } 
28. return vetEnviaFuncionarios; 
29. } 
30. public static ArrayList RecuperaObjetosPorDepartamento(String pOID){ 
31. ArrayList vetEnviaFuncionarios = new ArrayList(); 
32. IList listFuncionarios = 
Funcionario.RecuperaObjetosPorDepartamento(pOID); 
33. for (int i = 0; i < listFuncionarios.Count; i++) 
34. { 
35. Funcionario objBuffer = (Funcionario)listFuncionarios[i]; 
36. String[] vBuffer = new String[3]; 
37. vBuffer[0] = objBuffer.Codigo; 
38. vBuffer[1] = objBuffer.Nome; 
39. vBuffer[2] = Convert.ToString(objBuffer.calcularSalario()); 
40. vetEnviaFuncionarios.Add(vBuffer); 
41. } 
42. return vetEnviaFuncionarios; 
43. } 
44. public static Boolean Excluir(String pID){ 
45. return Funcionario.Excluir(pID); 
46. } 
47. public static int ContabilizaFuncionariosPorDepartamento(String 
pIDDepartamento){ 
48. return 
FuncionarioDAO.ContabilizaFuncionariosPorDepartamento(pIDDepartamento); 
49. } 
50. } 
51. } 
 
Na Listagem 4, a classe cntrFuncionario apresenta três métodos estáticos, responsáveis pela 
manipulação genérica de objetos de toda a hierarquia da classe Funcionario. O primeiro é o 
RecuperaObjetos responsável por retornar à interface, um vetor aninhado com todos os objetos do 
tipo Funcionario da base de dados. 
Para isso, é invocado o RecuperaObjetos da classe Funcionario, que retorna uma coleção de 
objetos. Com essa coleção, é então montado o vetor com os dados de cada funcionário, que será 
retornado à interface. O método RecuperaObjetosPorDepartamento faz ação semelhante ao 
RecuperaObjetos, mas filtrando os funcionários por um determinado departamento. Para isso, o 
método recebe por parâmetro o OID (Object Identification – Atributo identificador) do 
departamento. Desta forma, o método invoca então o método da classe Funcionario 
RecuperaObjetosPorDepartamento. Já o método Excluir se responsabiliza em receber como 
parâmetro uma string representando o OID do objeto que a interface deseja excluir e aciona o 
Excluir da classe Funcionario. 
 
Listagem 5. Definição da Classe cntrFuncionarioHorista 
1. using System; 
2. using System.Collections.Generic; 
3. using System.Collections; 
 
 
4. using System.Text; 
5. using Empresa.Model; 
6. 
7. namespace Empresa.Controller{ 
8. class cntrFuncionarioHorista{ 
9. private FuncionarioHorista objFuncionarioHorista; 
10. public cntrFuncionarioHorista(){ 
11. } 
12. public Boolean Salvar(ArrayList pLista){ 
13. if (pLista[0] == null){ 
14. //Criar um Novo 
15. this.objFuncionarioHorista = new FuncionarioHorista(); 
16. this.objFuncionarioHorista.Codigo = System.Guid.NewGuid().ToString(); 
17. this.objFuncionarioHorista.Nome = Convert.ToString(pLista[1]); 
18. this.objFuncionarioHorista.CPF = Convert.ToString(pLista[2]); 
19. this.objFuncionarioHorista.Departamento = 
Departamento.RecuperaObjeto(Convert.ToString(pLista[3])); 
20. this.objFuncionarioHorista.NumDiasTrabalhados = 
Convert.ToInt16(pLista[4]); 
21. this.objFuncionarioHorista.NumHorasDiaTrabalhado = 
Convert.ToInt16(pLista[5]); 
22. this.objFuncionarioHorista.ValorHora = Convert.ToInt16(pLista[6]); 
23. if (objFuncionarioHorista.Persistir()){ 
24. return true; 
25. } 
26. else{ 
27. return false; 
28. } 
29. } 
30. else{ 
31. //Atualização 
32. this.objFuncionarioHorista = 
(FuncionarioHorista)Funcionario.RecuperaObjeto(pLista[0].ToString()); 
33. this.objFuncionarioHorista.Nome = Convert.ToString(pLista[1]); 
34. this.objFuncionarioHorista.CPF = Convert.ToString(pLista[2]); 
35. this.objFuncionarioHorista.Departamento = 
Departamento.RecuperaObjeto(Convert.ToString(pLista[3])); 
36. this.objFuncionarioHorista.NumDiasTrabalhados = 
Convert.ToInt32(pLista[4]); 
37. this.objFuncionarioHorista.NumHorasDiaTrabalhado = 
Convert.ToInt32(pLista[5]); 
38. this.objFuncionarioHorista.ValorHora = Convert.ToInt32(pLista[6]); 
39. if (objFuncionarioHorista.Atualizar()){ 
40. return true; 
41. } 
42. else{ 
43. return false; 
44. } 
45. } 
46. } 
47. public ArrayList RecuperaObjeto(String pOID){ 
48. ArrayList vetEnvia = new ArrayList(); 
49. this.objFuncionarioHorista = 
(FuncionarioHorista)Funcionario.RecuperaObjeto(pOID); 
50. vetEnvia.Add(this.objFuncionarioHorista.Codigo); 
51. vetEnvia.Add(this.objFuncionarioHorista.Nome); 
52. vetEnvia.Add(this.objFuncionarioHorista.CPF); 
53. vetEnvia.Add(this.objFuncionarioHorista.Departamento.Codigo); 
54. vetEnvia.Add(this.objFuncionarioHorista.NumDiasTrabalhados); 
55. vetEnvia.Add(this.objFuncionarioHorista.NumHorasDiaTrabalhado); 
56. vetEnvia.Add(this.objFuncionarioHorista.ValorHora); 
57. return vetEnvia; 
58. } 
59. } 
60. } 
 
Na Listagem 5 é apresentada a classe cntrFuncionarioHorista. O primeiro método 
apresentado é o Salvar, que é invocado pela interface quando o usuário aciona essa opção no 
formulário. Ele recebe como parâmetro um ArrayList com os dados do FuncionarioHorista. É de 
 
 
responsabilidade da interface, pegar os dados digitados pelo usuário no formulário e montar esse 
vetor. 
O método então verifica se é uma operação de atualização ou de criação. Caso seja de 
atualização é invocado o Atualizar (linha 39) do objeto. Para o outro caso, é acionado o método 
Persistir (linha 23). No caso de criação de um novo funcionário, é atribuído ao código do objeto, 
um novo OID, usando a estratégia do GUID (linha 16). 
O segundo método apresentado é o RecuperaObjeto, que recebe como parâmetro uma string, 
representando o OID do objeto que a interface deseja recuperar. O método então invoca o 
RecuperaObjeto da classe FuncionarioHorista e monta um vetor com os seus dados e o devolve 
para a interface. A interface então pode tratar da forma que lhe for conveniente. 
A classe controladora do Departamento, a cntrDepartamento possui definição semelhante as 
já apresentadas e por isso não esta sendo definida. 
 
Nota: O código-fonte completo da aplicação esta disponível para download. 
 
 
Mapeamento Objeto-Relacional e Banco de Dados 
 
O mapeamento objeto-relacional é uma abordagem que permite a construção de sistemas 
utilizando o paradigma Orientado a Objetos com a persistência desses objetos em bancos dedados 
relacionais. Utilizando-se de técnicas e estratégias específicas, é possível mapear classes com seus 
atributos e associações para o modelo relacional. 
Utiliza-se uma abstração bastante intuitiva no sentido de que uma classe pode ser mapeada 
para uma tabela no banco de dados relacional e atributos da classe para campos da tabela. Porém, 
algumas diferenças entre os dois modelos, como o OID, tipos de dados, herança e associações, 
demandam um estudo mais detalhado das estratégias de mapeamento. 
Para o estudo de caso, a construção da base de dados seguiu esse raciocínio. A classe 
Departamento foi mapeada para a tabela Departamento, com seus atributos sendo os campos da 
tabela e a hierarquia Funcionario e FuncionarioHorista sendo mapeada para as tabelas Funcionario 
e FuncionarioHorista, cada uma com os seus respectivos atributos sendo os campos das tabelas 
Para estabelecer a hierarquia, a chave primária da tabela FuncionarioHorista é a mesma chave 
primária da tabela Funcionario, estabelecendo assim uma relação de chave primária estrangeira. 
Existem outras duas possíveis alternativas para se mapear uma hierarquia: criar uma única 
tabela, com todos os atributos como campos da tabela, com um campo adicional chamado tipo, que 
representa a classe que instanciou cada objeto ou criar uma nova tabela para cada classe concreta, 
contendo os seus atributos, mais os atributos da classe abstrata. 
Assim, a Listagem 6 apresenta o script para criação do banco, resultante do mapeamento 
objeto-relacional realizado com as classes do estudo de caso. A base de dados utilizada para o 
estudo de caso é o SQL SERVER 2005 Express Edition. No entanto, qualquer outra base seria 
suportada nesta arquitetura. 
 
Listagem 6. Script para criação das tabelas no banco de dados 
CREATE TABLE Departamento( 
 ID varchar(38) NOT NULL PRIMARY KEY, 
 Descricao varchar(50) NOT NULL, 
) 
CREATE TABLE Funcionario( 
 ID varchar(38) NOT NULL PRIMARY KEY, 
 Nome varchar(50) NOT NULL, 
 CPF varchar(14) NOT NULL, 
 DepartamentoOID varchar(38) NOT NULL, 
) 
CREATE TABLE FuncionarioHorista( 
 ID varchar(38) NOT NULL PRIMARY KEY, 
 NumDiasTrabalhados int NOT NULL, 
 
 
 NumHorasDiaTrabalhado int NOT NULL, 
 ValorHora int NOT NULL, 
) 
ALTER TABLE Funcionario ADD CONSTRAINT fk_DPTOOID 
 FOREIGN KEY(DepartamentoOID) REFERENCES Departamento(ID) 
ALTER TABLE FuncionarioHorista ADD CONSTRAINT fk_DPTOOID 
 FOREIGN KEY(ID) REFERENCES Funcionario(ID) 
 
 
Classes de Persistência e Manipulação de Objetos 
Conforme já apresentado, o namespace Persistence constitui uma importante parte da 
aplicação. A parte que é responsável pela persistência e manipulação dos objetos no banco de dados 
relacional. Neste são definidas as classes que representam um padrão de projeto chamado DAO – 
Data Access Object – que, basicamente, define o encapsulamento do acesso aos dados por meio de 
classes especificamente construídas para essa tarefa. Assim, para cada classe persistente do modelo 
existe uma classe DAO correspondente. 
No entanto, antes de se utilizar os métodos das classes DAO, é necessário se conectar e 
autenticar no banco de dados e configurar o catálogo correspondente no SQL SERVER que possui a 
estrutura de tabelas já apresentadas. Para isso, dentro do namespace Persistence, foi criada uma 
classe com o nome FabricaConexao, com objetivo de centralizar a conexão com a base de dados 
em um único lugar e certificando que ela será feita somente uma única vez ao carregar a aplicação. 
Essa classe é a implementação de um padrão de projeto criacional chamado Singleton, que 
garante que uma classe possua apenas uma única instância fornecendo um ponto global de acesso 
para a mesma, através de atributos e definições estáticas (static). Com isso é disponibilizado à 
classe um ponto global e único de conexão à base de dados, necessário para a persistência e 
manipulação dos objetos de forma eficaz e eficiente. A Listagem 7 apresenta a definição dessa 
classe (crie um arquivo CS - FabricaConexao.cs - semelhante aos exemplos anteriores dentro do 
namespace Persistence). 
 
Listagem 7. Definição da Classe FabricaConexao 
1. using System; 
2. using System.Collections.Generic; 
3. using System.Text; 
4. using System.Data.SqlClient; 
5. 
6. namespace Empresa.Persistence{ 
7. public class FabricaConexao{ 
8. private String stringconnection = "Data Source=NOTEBK-DAIBERT\\SQLEXPRESS; 
Initial Catalog=Empresa;Integrated Security=SSPI;MultipleActiveResultSets=True"; 
9. private static SqlConnection objConexao = null; 
10. 
11. public FabricaConexao(){ 
12. objConexao = new SqlConnection(); 
13. objConexao.ConnectionString = stringconnection; 
14. objConexao.Open(); 
15. } 
16. public static SqlConnection getConexao(){ 
17. if (objConexao == null){ 
18. new FabricaConexao(); 
19. } 
20. return objConexao; 
21. } 
22. public static void fecharConexao(){ 
23. objConexao.Close(); 
24. } 
25. } 
26. } 
 
A Listagem 7, define a classe FabricaConexao. Esta classe faz uso, para este caso de uso, da 
classe SqlConnection, disponibilizada em System.Data.SqlClient (linha 4). Ela possui dois atributos: 
stringconnection, que armazena em uma string a string de conexão para o banco de dados, 
 
 
configurando o servidor, o catálogo, forma de autenticação, e o atributos objConexao, este do tipo 
SqlConnection que é o responsável por realizar a conexão com o banco de dados com os dados 
definidos na stringconnection. Entre as linhas 11 e 15 é definido o método construtor da classe. Este 
instancia um objeto SqlConnection no atributo objConexao, configura a string de conexão e aciona 
o método Open. Este se conecta no banco de dados e mantém um ponteiro na base de dados 
autenticada para que aplicação faça uso. Entre as linhas 16 e 21, é definido o método getConexao. 
Este disponibiliza o objConexao à aplicação. Observe que este método verifica se o objConexao é 
null. Se for, ele invoca o método construtor que por sua vez, como definido, irá instanciar 
objConexao. Desta forma, garante-se que esta instancia é única em toda a aplicação. Toda 
solicitação de conexão ao banco de dados é centralizada nesta classe a sempre feita através deste 
método getConexao. Por fim, na linha 22, é definido o método fecharConexao. Este tem como 
objetivo fechar a conexão com o banco de dados, utilizada somente quando a aplicação se finaliza 
no estudo de caso. 
Com isso, é possível analisar as definições das classes DAO. Como já apresentado, cada 
classe do modelo (Funcionario, FuncionarioHorista e Departamento) possui o seu DAO 
correspondente. Desta forma, tem-se: FuncionarioDAO, FuncionarioHoristaDAO e 
DepartamentoDAO. Todos definidos de forma autônoma, cada um em uma classe dentro do 
namespace Persistence. As Listagens 8 e 9 definem as classes FuncionarioDAO e 
FuncionarioHoristaDAO respectivamente. Observe que as classes DAO recebem as chamadas das 
classes do modelo (classes de domínio) e são as únicas da aplicação que acessam o banco de dados, 
respeitando assim o que fora definido referente à programação em camadas. Diferentemente como 
observado quando se é utilizado um framework de persistência, como o nHibernate, nesta 
abordagem, as classes DAO manipulam os objetos com SQL diretamente em seus métodos. 
Novamente, para fins do estudo de caso, é omitida a classe DAO correspondente ao 
Departamento, pois esta possui definição muito semelhante às apresentadas. 
 
Listagem 8. Definição da Classe FuncionarioDAO 
1. using System; 
2. using System.Collections; 
3. using System.Text; 
4. using System.Data.SqlClient; 
5. using Empresa.Model; 
6. using Empresa.Controller; 
7. 
8. namespace Empresa.Persistence{ 
9. classFuncionarioDAO{ 
10. public FuncionarioDAO(){ 
11. } 
12. public static Funcionario recuperaObjeto(String pID){ 
13. SqlConnection objConexao = FabricaConexao.getConexao(); 
14. String strQuery = "SELECT ID, Nome, CPF, DepartamentoOID FROM 
Funcionario WHERE ID = '"+pID+"'"; 
15. SqlCommand objCommand = new SqlCommand(strQuery, objConexao); 
16. cntrDepartamento objControllerDepartamento = new cntrDepartamento(); 
17. SqlDataReader objLeitor2; 
18. Funcionario objFuncionario = null; 
19. FuncionarioHorista objFuncionarioHorista; 
20. try{ 
21. objCommand.ExecuteNonQuery(); 
22. SqlDataReader objLeitor = objCommand.ExecuteReader(); 
23. while (objLeitor.Read()){ 
24. //Verificar Tipo do Funcionário e Recuperar o Restante do 
Funcionário 
25. //Tentar em Todos os Filhos, até encontrar a Chave Primária 
Estrangeira Igual 
26. strQuery = "SELECT ID, NumDiasTrabalhados, 
NumHorasDiaTrabalhado, ValorHora FROM FuncionarioHorista WHERE ID = '" + objLeitor[0] + 
"'"; 
27. objCommand = new SqlCommand(strQuery, objConexao); 
28. objCommand.ExecuteNonQuery(); 
29. objLeitor2 = objCommand.ExecuteReader(); 
 
 
30. while (objLeitor2.Read()){ 
31. objFuncionarioHorista = new FuncionarioHorista(); 
32. objFuncionarioHorista.NumDiasTrabalhados = 
Convert.ToInt32(objLeitor2[1]); 
33. objFuncionarioHorista.NumHorasDiaTrabalhado = 
Convert.ToInt32(objLeitor2[2]); 
34. objFuncionarioHorista.ValorHora = 
Convert.ToInt32(objLeitor2[3]); 
35. objFuncionarioHorista.Codigo = 
Convert.ToString(objLeitor[0]); 
36. objFuncionarioHorista.Nome = Convert.ToString(objLeitor[1]); 
37. objFuncionarioHorista.CPF = Convert.ToString(objLeitor[2]); 
38. objFuncionarioHorista.Departamento = 
objControllerDepartamento.RecuperaObjetoObjeto(Convert.ToString(objLeitor[3])); 
39. objFuncionario = (Funcionario)objFuncionarioHorista; 
40. } 
41. //Fim Tentativas de Descobrir Tipo Funcionário 
42. } 
43. objLeitor.Close(); 
44. return objFuncionario; 
45. }catch (SqlException err){ 
46. String strErro = "Erro: " + err.ToString(); 
47. Console.Write(strErro); 
48. return objFuncionario; 
49. } 
50. } 
51. public static IList recuperaObjetosPorDepartamento(String pOID){ 
52. IList listFuncionarios = new ArrayList(); 
53. SqlConnection objConexao = FabricaConexao.getConexao(); 
54. String strQuery = "SELECT ID, Nome, CPF, DepartamentoOID FROM 
Funcionario WHERE DepartamentoOID = '"+pOID+"'"; 
55. SqlCommand objCommand = new SqlCommand(strQuery, objConexao); 
56. cntrDepartamento objControllerDepartamento = new cntrDepartamento(); 
57. SqlDataReader objLeitor2; 
58. try{ 
59. objCommand.ExecuteNonQuery(); 
60. SqlDataReader objLeitor = objCommand.ExecuteReader(); 
61. while (objLeitor.Read()){ 
62. //Verificar Tipo do Funcionário e Recuperar o Restante do 
Funcionário 
63. //Tentar em Todos os Filhos, até encontrar a Chave Primária 
Estrangeira Igual 
64. strQuery = "SELECT ID, NumDiasTrabalhados, 
NumHorasDiaTrabalhado, ValorHora FROM FuncionarioHorista WHERE ID = '" + objLeitor[0] + 
"'"; 
65. objCommand = new SqlCommand(strQuery, objConexao); 
66. objCommand.ExecuteNonQuery(); 
67. objLeitor2 = objCommand.ExecuteReader(); 
68. while (objLeitor2.Read()){ 
69. FuncionarioHorista objFuncionario = new 
FuncionarioHorista(); 
70. objFuncionario.NumDiasTrabalhados = 
Convert.ToInt32(objLeitor2[1]); 
71. objFuncionario.NumHorasDiaTrabalhado = 
Convert.ToInt32(objLeitor2[2]); 
72. objFuncionario.ValorHora = Convert.ToInt32(objLeitor2[3]); 
73. objFuncionario.Codigo = Convert.ToString(objLeitor[0]); 
74. objFuncionario.Nome = Convert.ToString(objLeitor[1]); 
75. objFuncionario.CPF = Convert.ToString(objLeitor[2]); 
76. objFuncionario.Departamento = 
objControllerDepartamento.RecuperaObjetoObjeto(Convert.ToString(objLeitor[3])); 
77. listFuncionarios.Add(objFuncionario); 
78. } 
79. //Fim Tentativas de Descobrir Tipo Funcionário 
80. } 
81. objLeitor.Close(); 
82. return listFuncionarios; 
83. }catch (SqlException err){ 
84. String strErro = "Erro: " + err.ToString(); 
85. Console.Write(strErro); 
 
 
86. return listFuncionarios; 
87. } 
88. } 
89. public static IList recuperaObjetos(){ 
90. IList listFuncionarios = new ArrayList(); 
91. SqlConnection objConexao = FabricaConexao.getConexao(); 
92. String strQuery = "SELECT ID, Nome, CPF, DepartamentoOID FROM 
Funcionario"; 
93. SqlCommand objCommand = new SqlCommand(strQuery, objConexao); 
94. cntrDepartamento objControllerDepartamento = new cntrDepartamento(); 
95. SqlDataReader objLeitor2; 
96. try{ 
97. objCommand.ExecuteNonQuery(); 
98. SqlDataReader objLeitor = objCommand.ExecuteReader(); 
99. while (objLeitor.Read()) { 
100. //Verificar Tipo do Funcionário e Recuperar o Restante do 
Funcionário 
101. //Tentar em Todos os Filhos, até encontrar a Chave Primária 
Estrangeira Igual 
102. strQuery = "SELECT ID, NumDiasTrabalhados, 
NumHorasDiaTrabalhado, ValorHora FROM FuncionarioHorista WHERE ID = '"+objLeitor[0]+"'"; 
103. objCommand = new SqlCommand(strQuery, objConexao); 
104. objCommand.ExecuteNonQuery(); 
105. objLeitor2 = objCommand.ExecuteReader(); 
106. while (objLeitor2.Read()){ 
107. FuncionarioHorista objFuncionario = new 
FuncionarioHorista(); 
108. objFuncionario.NumDiasTrabalhados = 
Convert.ToInt32(objLeitor2[1]); 
109. objFuncionario.NumHorasDiaTrabalhado = 
Convert.ToInt32(objLeitor2[2]); 
110. objFuncionario.ValorHora = Convert.ToInt32(objLeitor2[3]); 
111. objFuncionario.Codigo = Convert.ToString(objLeitor[0]); 
112. objFuncionario.Nome = Convert.ToString(objLeitor[1]); 
113. objFuncionario.CPF = Convert.ToString(objLeitor[2]); 
114. objFuncionario.Departamento = 
objControllerDepartamento.RecuperaObjetoObjeto(Convert.ToString(objLeitor[3])); 
115. listFuncionarios.Add(objFuncionario); 
116. } 
117. //Fim Tentativas de Descobrir Tipo Funcionário 
118. } 
119. objLeitor.Close(); 
120. return listFuncionarios; 
121. } 
122.catch (SqlException err){ 
123. String strErro = "Erro: " + err.ToString(); 
124. Console.Write(strErro); 
125. return listFuncionarios; 
126. } 
127. } 
128. public static Boolean excluir(String pID){ 
129. SqlConnection objConexao = FabricaConexao.getConexao(); 
130. //Criar query para deletar o funcionario associado. Criar query para 
todos os tipos. 
131. String strQuery = "DELETE FROM Funcionario WHERE ID = '" + pID + "'"; 
132. strQuery = strQuery + "; DELETE FROM FuncionarioHorista WHERE ID = '"+ 
pID +"'"; 
133. //Caso tivesse mais tipos, adicionar a query para todos os tipos, por 
exemplo FuncionarioDiarista caso existisse: 
134. //strQuery = strQuery + "; DELETE FROM FuncionarioDiarista WHERE ID = '" 
+ pID + "'"; 
135. //Desta forma todo tipo de funcionário seria deletado, sem que seja 
necessário descobrir o seu tipo específico. A query não retorna erro quando não encontra 
o objeto na clausula WHERE 
136. SqlCommand objCommand = new SqlCommand(strQuery, objConexao); 
137. try{ 
138. objCommand.ExecuteNonQuery(); 
139. return true; 
140. }catch (SqlException err){ 
141. String strErro = "Erro: " + err.ToString(); 
 
 
142. Console.Write(strErro); 
143. return false; 
144. } 
145. } 
146. public static int ContabilizaFuncionariosPorDepartamento(String 
pIDDepartamento) { 
147. SqlConnection objConexao = FabricaConexao.getConexao(); 
148. String strQuery = "SELECT COUNT(*) FROM Funcionario WHERE 
DepartamentoOID = '"+pIDDepartamento+"'"; 
149. SqlCommand objCommand = new SqlCommand(strQuery, objConexao); 
150. int vRetorno = 0; 
151. try{ 
152. objCommand.ExecuteNonQuery(); 
153. SqlDataReader objLeitor = objCommand.ExecuteReader(); 
154. while (objLeitor.Read()) 
155. { 
156. vRetorno = Convert.ToInt32(objLeitor[0]); 
157. } 
158. return vRetorno; 
159. }catch (SqlException err){ 
160. String strErro = "Erro: " + err.ToString(); 
161. Console.Write(strErro); 
162. return vRetorno; 
163. } 
164. } 
165. } 
166. } 
 
Em toda a estrutura DAO, existem basicamente os seguintes métodos: recuperaObjeto 
(recupera um objeto em específico da classe referenciada), recuperaObjetos (recupera todos os 
objetos da classe referenciada), persistir (persiste um objeto no banco de dados), atualizar (atualiza 
um objeto em específico com novas informações) e excluir (excluir um objeto especifico). Outros 
métodos são definidos, mas as chamadas operações CRUD (CREATE, RETRIEVE, UPDATE e 
DELETE) são feitas por estes apresentados. O CRUD representa todas as operações básicas 
necessárias para a persistência e manipulação de objetos em uma base de dados relacional. 
A Listagem 8 inicia importando as bibliotecas e os namespaces que fará uso. Isso ocorre 
entre as linhas 1 e 6. Da linha 12 até a 50 é definido o método recuperaObjeto. Este método recebe 
por parâmetro o atributo identificador de um Funcionário que ao final do método é recuperado da 
base de dados e disponibilizado à aplicação. Na linha 13 é feito a solicitação à classe 
FabricaConexao pelo objeto de conexão. Com este, é possível estabelecer consultar no banco de 
dados configurado. Na linha 14, é definida uma variável chamada strQuery. Esta variável armazena 
a consulta SQL que será enviada para o banco de dados. Observe que neste caso esta sendo feito um 
SELECT, solicitando os campos ID, Nome, CPF, DepartamentoOID da tabela Funcionario que 
tenha o ID passado por parâmetro. Após, na linha 15, é instanciado um objeto do tipo SqlCommand, 
responsável por executar a consulta na base de dados, configurada pela conexão recebida pelo 
FabricaConexao. Entre as linhas 23 e 44, é feito um esforço para recuperar as informações da base 
de dados e então popular um objeto, que é então retornado como retorno do método. Na linha 38, é 
solicitado ao controlador de Departamento que recupere o objeto Departamento associado ao 
Funcionário, já que todo funcionário deve estar alocado em um departamento. O método 
RecuperaObjetoObjeto, da classe cntrDepartamento é um método de classe que retorna um objeto 
Departamento de acordo com o parâmetro passado. A partir da linha 23 o método busca identificar 
o tipo do funcionário para recuperar todas as informações e que seja instanciado um objeto de forma 
correta da hierarquia. 
Entre as linhas 89 e 127 é definido o método recuperaObjetos. Este recupera todos os objetos 
da base de dados. O seu funcionamento é semelhante ao recuperaObjeto, mas com uma diferença: 
não é retornado um objeto, mas sim uma lista de objetos – todos os persistidos na base de dados. O 
tipo de retorno do método é IList, que é a interface da classe Collections. O que permite a utilização 
da classe ArrayList, como definido na linha 90. Já entre as linhas 128 e 145 é apresentado o método 
 
 
excluir. Este recebe o atributo identificador do funcionário como parâmetro e o excluir da base de 
dados, retornando verdadeiro em caso de sucesso e falso em caso de insucesso. 
Nas linhas 146 à 164 é definido o método ContabilizaFuncionariosPorDepartamento. Este 
método faz uma contagem no banco de dados de quantos funcionários existem em um determinado 
departamento. Por fim, entre as linhas 51 e 88 é apresentado o método 
recuperaObjetosPorDepartamento. Este responsável por recuperar uma lista de funcionários de um 
determinado departamento. Para isso é feita uma consulta restritiva no campo DepartamentoOID, 
como pode ser observado na linha 54. 
 
Listagem 9. Definição da Classe FuncionarioHoristaDAO 
1. using System; 
2. using System.Collections.Generic; 
3. using System.Text; 
4. using Empresa.Model; 
5. using System.Data.SqlClient; 
6. 
7. namespace Empresa.Persistence{ 
8. class FuncionarioHoristaDAO{ 
9. public FuncionarioHoristaDAO(){ 
10. } 
11. public Boolean persistir(FuncionarioHorista pFunHorista){ 
12. SqlConnection objConexao = FabricaConexao.getConexao(); 
13. String strQuery = "INSERT INTO Funcionario VALUES('" + pFunHorista.Codigo 
+ "','" + pFunHorista.Nome + "','"+ pFunHorista.CPF 
+"','"+pFunHorista.Departamento.Codigo+"')"; 
14. strQuery = strQuery + "; INSERT INTO FuncionarioHorista VALUES 
('"+pFunHorista.Codigo+"','"+pFunHorista.NumDiasTrabalhados+"','"+pFunHorista.NumHorasDia
Trabalhado+"','"+pFunHorista.ValorHora+"')"; 
15. SqlCommand objCommand = new SqlCommand(strQuery, objConexao); 
16. try{ 
17. objCommand.ExecuteNonQuery(); 
18. return true; 
19. }catch (SqlException err){ 
20. String strErro = "Erro: " + err.ToString(); 
21. Console.Write(strErro); 
22. return false; 
23. } 
24. } 
25. public Boolean atualizar(FuncionarioHorista pFunHorista){ 
26. SqlConnection objConexao = FabricaConexao.getConexao(); 
27. String strQuery = "UPDATE Funcionario SET Nome = '" + pFunHorista.Nome + 
"', CPF = '"+pFunHorista.CPF+"', DepartamentoOID = '"+pFunHorista.Departamento.Codigo+"' 
WHERE ID = '" + pFunHorista.Codigo + "'"; 
28. strQuery = strQuery + "UPDATE FuncionarioHorista SET NumDiasTrabalhados = 
'"+pFunHorista.NumDiasTrabalhados+"', NumHorasDiaTrabalhado = 
'"+pFunHorista.NumHorasDiaTrabalhado+"', ValorHora = '"+pFunHorista.ValorHora+"' WHERE ID 
= '"+pFunHorista.Codigo+"'";28. SqlCommand objCommand = new SqlCommand(strQuery, objConexao); 
30. try{ 
31. objCommand.ExecuteNonQuery(); 
32. return true; 
33. }catch (SqlException err){ 
34. String strErro = "Erro: " + err.ToString(); 
35. Console.Write(strErro); 
36. return false; 
37. } 
38. } 
39. } 
40. } 
 
A classe FuncionarioHoristaDAO esta sendo apresentada pela Listagem 9. Em estrutura 
semelhante à classe FuncionarioDAO, esta apresenta dois métodos: persistir e atualizar. O persistir 
é responsável por salvar um objeto FuncionarioHorista no banco de dados e o atualizar por 
atualizá-lo. Em cada um dos métodos são definidos um SQL referente a cada operação. Em ambos 
os casos, é retornado verdadeiro em caso de sucesso e falso em caso de insucesso. 
 
 
Buscando exemplificar o funcionamento da arquitetura do sistema proposto, é apresentado de 
forma detalhada a funcionalidade Cadastrar Funcionário Horista. A Figura 6 exibe o diagrama de 
seqüência, com o objetivo de nortear os passos realizados para esse cenário. 
 
 
Figura 6. Diagrama de Seqüência para a Funcionalidade Cadastrar Funcionário Horista 
 
 
Nota: O código-fonte completo da aplicação está disponível para download. 
 
O caso de uso inicia, quando o usuário acessa a interface e aciona a opção Adicionar Novo 
Funcionário Horista. Esse por sua vez acessa o controlador da classe Departamento 
(cntrDepartamento) para alimentar o ComboBox com todos os departamentos, invocando o 
RecuperaObjetos. Esse, por sua vez, aciona o RecuperaObjetos da classe Departamento, que acessa 
o método recuperaObjetos da classe DepartamentoDAO para recuperar os departamentos da base 
de dados. 
Com o ComboBox montado, é exibido o formulário de criação de um novo funcionário como 
exemplificado na Figura 7. 
 
 
Figura 7. Interface do formulário de um novo funcionário horista 
 
O usuário informa então os dados do novo funcionário e aciona o Salvar. Nesse ponto, o 
formulário (frmNovoFuncionarioHorista) monta um vetor (vetEnvia) com os dados do funcionário 
e passa como parâmetro ao Salvar do controlador da classe FuncionarioHorista 
(cntrFuncionarioHorista). 
 
 
Esse, por sua vez, instancia um novo objeto do tipo FuncionarioHorista, e atribui os valores 
do vetor ao objeto. Com o objeto montado, é invocado o seu método Persistir. Este faz o acesso à 
classe FuncionarioHoristaDAO, que inicialmente resgata da classe FabricaConexao uma nova 
seção de conexão com o banco de dados (getConexao) e gera o SQL para inserir as novas 
informações na base de dados. Este então executa o SQL na base de dados persistindo o objeto. 
Caso todas as operações tenham sido realizadas com sucesso, é retornado true para todos os 
métodos até a interface. Caso tenha ocorrido algum erro, é retornado false para a interface que se 
responsabiliza em emitir uma mensagem de erro ao usuário. 
Somente a interface tem acesso ao usuário nessa abordagem, portanto, somente ela pode 
enviar notificações de erros ou de sucesso. Após, uma consulta ao banco de dados pode verificar a 
persistência dos objetos. 
 
Conclusão 
Este artigo teve como objetivo abordar de forma prática a utilização do paradigma Orientado 
a Objetos no contexto do desenvolvimento de software no ambiente do Visual Studio na linguagem 
C# .NET e de técnicas aliadas, como mapeamento objeto relacional e utilização de padrões de 
desenvolvimento. 
Foi possível observar na prática como realizar de forma simples a persistência e manipulação 
de objetos utilizando um banco de dados relacional, apoiado por padrões de desenvolvimento, como 
o padrão de projeto DAO (Data Access Object), que encapsula todo o contexto de conexão e 
comunicação com o banco de dados. 
Atualmente, essa abordagem tem uma grande aceitação, uma vez que os bancos de dados 
Orientados a Objetos ainda não são o padrão de mercado, tornando possível a união entre os 
conceitos da Orientação a Objetos, com o desempenho, maturidade e confiabilidade dos bancos de 
dados relacionais.

Outros materiais