ORIENTACAO A OBJETOS - CONCEITO

KERPLUNK 08/05/2013 12:04:32
#423116
Ok, vou fazer um e publico assim que terminar.
KERPLUNK 08/05/2013 18:39:03
#423140
Conforme prometido, aqui está o exemplo. Fiz na pressa, usando OleDb, mas já vai servir para ilustrar.

Quem quiser, ministro aulas pela internet, ensinando isso e muito, mas muito mais, em um precinho camarada! Já faço isso com alguns usuários do VBMania...
KERPLUNK 09/05/2013 08:48:28
#423163
Caramba, acho que ninguém entendeu o exemplo...
FFCOUTO 09/05/2013 14:07:57
#423191
Calma Kerplunk, estou estudando o exemplo, achei um pouco complexo ainda pra mim é uma mudança radical da programação procedural.

Outra coisa que você falou foi numa classe singleton para acesso a dados, eu tentei fazer uma aqui, pode dar uma olhada. Segue abaixo:


using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace DBFactory
{
public sealed class Database
{
private static readonly Database instance = new Database();

static SqlConnection conn = null;
SqlTransaction _transaction;
string _connString;
bool _transOpen;

private Database() { }
public static Database GetInstance { get { return instance; } }

public readonly SqlConnection ActiveConnection { get { return conn; } }
public bool KeepOpen { get; set; }

public bool OpenConnection(string ConnectionString, bool KeepOpen)
{
try
{
if (conn == null) conn = new SqlConnection();

if (conn.State == ConnectionState.Closed)
{
conn.ConnectionString = ConnectionString;
conn.Open();
}

this.KeepOpen = KeepOpen;
_connString = ConnectionString;

return true;
}

catch (Exception ex)
{
throw ex;
}
}

public void CloseConnection()
{
try
{
if (conn != null)
{
if (conn.State != ConnectionState.Closed)
{
if (!_transOpen) { conn.Close(); }
}
}
}

catch (Exception ex)
{
throw ex;
}
}

public SqlDataReader OpenRecordset(string SQLCommand, out int RecordCount)
{
try
{
if (!this.KeepOpen) { this.OpenConnection(_connString, this.KeepOpen); }

SqlCommand cmd = new SqlCommand(SQLCommand);
cmd.CommandType = CommandType.Text;
cmd.Prepare();

SqlDataReader dr = cmd.ExecuteReader();

RecordCount = dr.Depth;
return dr;
}

catch (Exception ex)
{
throw ex;
}
}

public bool BeginTransaction()
{
_transOpen = this.KeepOpen; // guarda a opção da propriedade KeepOpen
this.KeepOpen = true; // atribui a opção como sempre aberta

try
{
if (conn.State == ConnectionState.Closed) { this.OpenConnection(_connString, this.KeepOpen); }
if (_transaction == null) { _transaction = conn.BeginTransaction(); }
return true;
}

catch (Exception ex)
{
this.KeepOpen = _transOpen;
_transOpen = false;

if (_transaction != null) { _transaction.Rollback(); }
_transaction = null;

throw ex;
}
}

public bool CommitTransaction()
{
try
{
if (conn != null)
{
if (_transaction != null)
{
_transaction.Commit();
_transaction = null;
this.KeepOpen = _transOpen;
_transOpen = false;
}
}

if (!this.KeepOpen) { this.CloseConnection(); }
return true;
}

catch (Exception ex)
{
this.RollbackTransaction();
throw ex;
}
}

public void RollbackTransaction()
{
try
{
if (conn != null)
{
if (_transaction != null)
{
_transaction.Rollback();
this.KeepOpen = _transOpen;
_transOpen = false;
}
}

if (!this.KeepOpen) { this.CloseConnection(); }
_transaction = null;
}

catch (Exception ex)
{
if (conn != null)
{
if (_transaction != null) { _transaction.Rollback(); }
}

if (!this.KeepOpen) { this.CloseConnection(); }

this.KeepOpen = _transOpen;
_transOpen = false;
_transaction = null;

throw ex;
}
}

public bool Execute(string SQLCommand, out int RecordsAffected)
{
int lCount = 0;

try
{
if (!this.KeepOpen) { this.OpenConnection(_connString, this.KeepOpen); }

if (conn != null)
{
if (conn.State == ConnectionState.Open)
{
SqlCommand cmd = new SqlCommand(SQLCommand);
cmd.Connection = conn;
cmd.Prepare();
lCount = cmd.ExecuteNonQuery();
}
}

if (!this.KeepOpen) { this.CloseConnection(); }

RecordsAffected = lCount;
return true;
}

catch (Exception ex)
{
throw ex;
}
}

public DateTime GetDateTime()
{
DateTime dhServ = DateTime.Now;

try
{
//Abre uma conexão caso esta não fique aberta anteriormente
if (!this.KeepOpen) { this.OpenConnection(_connString, this.KeepOpen); }

// Recupera a data e hora atual do servidor
string sql = [Ô]SELECT GETDATE() AS hora_atual;[Ô];
SqlCommand cmd = new SqlCommand(sql);
cmd.Connection = conn;
cmd.Prepare();

SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read()) { dhServ = Convert.ToDateTime(dr[[Ô]hora_atual[Ô]]); }
dr.Close();
dr.Dispose();

// Fecha a conexão se não há opção de manter aberta
if (!this.KeepOpen) { this.CloseConnection(); }

// Retorna a data e hora atual do servidor
return dhServ;
}

catch
{
return DateTime.Now;
}
}
}
}
KERPLUNK 09/05/2013 14:16:41
#423194
Não testei, mas PARECE que sua classe está com o padrão singleton, basta usa-la de forma correta.
KERPLUNK 13/05/2013 10:25:36
#423368
Então, chegaram a avaliar o exemplo?
FFCOUTO 13/05/2013 10:57:37
#423370
Kerplunk, bom dia,

Avaliei sim o exemplo. Obviamente ainda há algumas dúvidas. De forma geral, escreve-se bem menos e como você mesmo citou, altera-se muito pouco coisa na programação.

Agora eu tenho uma dúvida que pra mim é a principal. No meu sistema, em algumas classes que fiz para trabalhar com as tabelas, tem propriedades do tipo somente leitura, e outras propriedades que são resultado de cálculos que são gravadas para melhorar o desempenho na hora de gerar relatórios. Por exemplo: no cadastro de clientes, tenho 2 campos para limite disponivel de crédito; já no lançamento de pedidos, eu gravo o resultado da multiplicação da quantidade pelo preço e outras deduções que são aplicadas. Como ficaria esses campos usando o seu exemplo?
FOXMAN 17/05/2013 14:20:01
#423658
Bem, eu tbem estou iniciando novos projetos e busco adequar os meus sistemas da melhor forma para uma melhor manutenção.
Uma pequena dúvida.

A implementação dos tratamentos de erros dever ser feitos onde ??

Na minha solução digamos que tenho as seguintes camadas....

Por ordem de acesso..

GUI
BLL
DAL

Na camada de apresentação eu disparo os messagebox.
Na camada Regras de negocios eu disparo novas Exception (throw new Excepion([Ô]bla.bla.bla[Ô]); de acordo com o erro.
Na camada de acesso a dados eu somente disparo as exception, que serão tratadas na camada de negócios e apresentadas na camada apresentação.

Minha dúvida é se o correto é não disparar messagbox nas camadas BLL e DAL.
FFCOUTO 17/05/2013 18:29:02
#423672
Fox,

Pelo que eu entendi as mensagens devem ser mostradas apenas na camada GUI.

Digamos que você vai validar os dados de um cadastro de clientes. Na BLL você teria uma função Validar(). Na GUI você chamaria esta função e ela te retornaria TRUE ou FALSE. Se há uma falha na validação você então mostraria a mensagem.

Algo assim.

if (!Clientes.Validar()) 
{
MessageBox.Show([Ô]Dados do cliente inválido.[Ô]);
return;
}


Creio que isso facilitaria o processo uma vez que você ao mudar as regras de validação não precisaria modificar nada na GUI.

FOXMAN 17/05/2013 22:11:49
#423682
Citação:

:
Fox,

Pelo que eu entendi as mensagens devem ser mostradas apenas na camada GUI.

Digamos que você vai validar os dados de um cadastro de clientes. Na BLL você teria uma função Validar(). Na GUI você chamaria esta função e ela te retornaria TRUE ou FALSE. Se há uma falha na validação você então mostraria a mensagem.

Algo assim.

if (!Clientes.Validar()) 
{
MessageBox.Show([Ô]Dados do cliente inválido.[Ô]);
return;
}


Creio que isso facilitaria o processo uma vez que você ao mudar as regras de validação não precisaria modificar nada na GUI.



Então Fabiano, eu faço dessa forma mesmo, no entanto todo o tratamento de erro eu que controlo.
Digamos que nesse VALIDAR() tenha ocorrido algum erro insesperado. Eu trato o erro na camada BLL e disparo uma nova Exception informando o erro.

Resumidamente seria assim : A camada apresentação envia solicitação de validação do cadastro dentro de um bloco try cath.

void btnSubMenu_Click(object sender, EventArgs e)
{
try
{

menus.ShowForm(pnlSubMenu, gbPrincipal, this, pnlInicio, Assembly.GetExecutingAssembly(), sender);
}
catch (Exception ex)
{

MessageBox.Show(ex.Message.ToString());
}
}


A BLL faz a validação dentro de um bloco try cath e envia para DAL.

Caso na validação já se tenha algum dado incompleto, eu disparo uma exception que será exibida na apresentação.

throw new excepton([Ô]bla...bla...bla[Ô]);

Na Camada de dados dentro de um bloco try cath executo as instruções de sql e caso ocorra um erro tbem disparo uma exception informando a mensagem detectada, que por sua vez passa pela BLL entrando diretamente no cath que por sua vez envia dispara a exception para a camada apresentação.

Parece complicado, porém o tratamento de erros que consegui imaginar seria este que exemplifiquei.
Pode não ser o correto, mas foi a forma que encontrei de fazer as camadas se comunicarem em relação a erros.

Se simplesmente ao tentar validar o cadastro do cliente e por algum erro eu retornar uma mensagem [Ô]Dados Inválidos[Ô], eu na verdade não saberia de onde partiu o erro, se foi na BLL ou na DAL.

Já fazendo da forma que exemplifiquei os erros são categorizados por camada, porém apresentados em apenas uma camada(Apresentação).

Na camada apresentação eu não tenho messageBox com texto definido como por exemplo messagebox([Ô]Dados Inválidos[Ô]), pois até então não sei que erro será retornado. Sendo assim as messagebox dos formulários são do tipo Genérica que pegam o texto da exception :


 void btnShowForm_Click(object sender, EventArgs e)
{
try
{
Clientes.Validar(Pessoa);
}
catch (Exception ex)
{

MessageBox.Show(ex.Message.ToString());
}
}







Página 2 de 14 [136 registro(s)]
Faça seu login para responder