Banco de Dados com Orientação a Objetos em ASP

Carlos Alberto (e-mail) é cursando em Sistemas de Informação com ênfase em segurança digital pela UniDF – Universidade do Distrito Federal, possui conhecimentos em Clipper, Java, ASP, ASP.NET e Delphi, trabalha no setor há 8 anos.

Olá amigos. Esta é a minha primeira publicação no iMasters agradeço à Redação pela oportunidade e espero que gostem das matérias.

O assunto que irei tratar aqui é um problema comum de programadores ASP: “O banco de dados”. Você, programador, está no meio do seu projeto e o seu chefe decide mudar o banco de dados. Agora, você tem que abrir página por página para corrigir. Fora o fato de você ter esparramado códigos SQL em todas as páginas. Fora o problema de segurança, onde você tem que tratar SQL injection, etc.

Como então proteger e simplificar o desenvolvimento? Uma idéia será utilizar o Design Pattern!

O que é um Design Pattern? É uma receita de como fazer algo muito difundido e testado. O Pattern que vamos ver neste artigo é o pattern DAO. Este Pattern simplifica o acesso aos dados, e você passa a utilizar apenas objetos, ou seja, nada de SQL, nada de Recordsets. Veja o esquema abaixo do que é o modelo DAO:

image005.jpgBanco de dados: Nesta camada está as suas tabelas.

Connection: É a ponte entre o DAO e o banco de dados.

DAO (Data Access Object): Objeto responsável por selecionar, incluir, atualizar e excluir dados nas tabelas.

DTO (Data Transfer Object): Objeto que representa a sua estrutura de registros do banco de dados.

Aplicação (business Object): Parte que utiliza o DAO.

Quais são os benefícios de utilizar esta estrutura?

. Aumento de transparência - A aplicação não precisa nem saber que banco de dados usa, nem como os dados são montados, visto que você passa a trabalhar com objetos apenas.

. Facilidade de migração - Os dados podem vir de qualquer lugar, como um xml, webservice ou um banco de dados, a migração para outras fontes basta apenas alterar o DAO, e a aplicação passará a utilizar o novo modelo de dados.

. Reduz a complexidade na aplicação - Se você não vai trabalhar com recordsets e SQLs, o código fica mais legível e mas fácil de programar.

. Centralização de acesso em uma camada separada - Com o Pattern DAO, você centraliza todo o acesso no DAO, facilitando a manutenção da aplicação.

Vamos então colocar a mão na massa? Veja o exemplo abaixo: para entender na prática como funciona tudo isso.

Exemplo de um cadastro de Clientes

O seu banco de dados possui a seguinte estrutura:

Tabela: Clientes
ID – Integer – AutoIncrement
Nome – Varchar(100)



O seu modelo DAO ficaria assim:

'DAOs
class clientes_dao
private m_lista
private M_StartPage
private M_MaxRows
private M_RecordCount
private M_OrderBy
dim M_Conn

Public Property Get StartPage()
Startpage = M_Startpage
end Property

Public Property Let Startpage(p_data)
M_Startpage = p_data
end Property

Public Property Get OrderBy()
OrderBy = M_Orderby
end Property

Public Property Let OrderBy(p_data)
M_OrderBy = p_data
end Property

Public Property Get RecordCount()
RecordCount = M_RecordCount
end Property

Public Property Let RecordCount(p_data)
end Property

Public Property Get MaxRows()
MaxRows = M_MaxRows
end Property

Public Property Let MaxRows(p_data)
M_MaxRows = p_data
end Property

Sub Class_Initialize()
M_StartRow = 0
M_MaxRows = 0
set m_lista = Server.CreateObject ("Scripting.Dictionary")
End Sub

Sub Class_Terminate()

Set m_conn = nothing
Set m_lista = nothing

End Sub

public function Initialize(conn)
Set M_Conn = conn
end Function

Public Function Insert(obj)

Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3
rs.Open "select * from clientes where 1=0 ",m_conn, 1, 2
ArrFlds= array("nome")
ArrValues = array(obj.nome)
rs.AddNew ArrFlds, ArrValues
rs.Update
Insert = rs(0)

rs.Close
Set rs = Nothing

End Function

Public Function Update(obj)
if not isnumeric(obj.id) or isEmpty(obj.id) then
U_id= 0
else
U_id=obj.id
end if
if not trim(obj.nome)="" then
U_nome=SingleQuotes(obj.nome)
else
U_nome=""
end if

strSQL = strSQL & " UPDATE clientes SET "
strSQL = Strsql& "nome ='"&U_nome&"'"

strSQL = strSQL & " where id= " &obj.id
chave=obj.id
if isnumeric(chave) and (not isempty(chave)) and chave<>0 then
m_conn.execute(strsql)
end if
End Function

function datainv(d)
if isdate(d) then datainv= year(d)&"-"&strzero(month(d),2)&"-"&strzero(day(d),2)
end function
private function strzero(v,z)
strzero=string(z-len(trim(cstr(v))),"0")&trim(cstr(v))
end function

Public Function Delete(key)
if isnumeric(key) and (not isempty(key)) and key<>0 then
m_conn.execute("delete from clientes where id="&key)
end if
End Function

Public Function FindAll() 'Objeto Scriting Dictinary

Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3
rs.Open "select * from clientes "&m_orderby,m_conn, 1, 3

FillFromRS(rs)
rs. close
set rs = nothing
set findall = m_lista
End Function

Public Function Findbywhere(pfilter) 'Objeto Scriting Dictinary
pfilter=SingleQuotes(pfilter)

Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3
rs.Open "select * from clientes where"&pfilter&" "&m_orderby,m_conn, 1, 3

FillFromRS(rs)
rs. close
set rs = nothing
set findbywhere = m_lista
End Function

Public Function FindByid(pfilter) 'Objeto Scriting Dictinary
if not isnumeric(pfilter) or isEmpty(pfilter) then
pfilter=0
else
pfilter=clng(pfilter)
end if

Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3
rs.Open "select * from clientes where id="&pfilter&" "&m_orderby,m_conn, 1, 3

FillFromRS(rs)
rs. close
set rs = nothing
set FindByid= m_lista
End Function

Public Function FindBynome(pfilter) 'Objeto Scriting Dictinary
if not trim(pfilter)="" or isEmpty(pfilter) then
pfilter=""
else
pfilter=SingleQuotes(cstr(pfilter))
end if

Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3
rs.Open "select * from clientes where nome like '"&pfilter&"' "&m_orderby,m_conn, 1, 3

FillFromRS(rs)
rs. close
set rs = nothing
set FindBynome= m_lista
End Function

private function SingleQuotes(pStringIn)
if pStringIn = "" or isnull(pStringIn) then exit function
Dim pStringModified
pStringModified = Replace(pStringIn,"'","''")
pStringModified = Replace(pstringmodified,"\","\\")
SingleQuotes = pStringModified
end function
private Function FillFromRS(p_RS)
dim myBook
m_recordcount=p_rs.recordcount
if m_recordcount > 0 then
if m_maxrows<>0 and m_startpage<>0 then
p_Rs.PageSize = m_maxrows
p_rs.AbsolutePage = m_startpage
set m_lista=nothing
set m_lista = Server.CreateObject ("Scripting.Dictionary")
Rc=0
do while ((Not p_Rs.eof) And (rc < p_Rs.PageSize))
set mybook = New DTO_clientes
MyBook.id = p_RS.fields("id").Value
MyBook.nome = p_RS.fields("nome").Value
m_lista.Add myBook.id, myBook
Rc= Rc + 1
p_RS.movenext
loop
else
set m_lista=nothing
set m_lista = Server.CreateObject ("Scripting.Dictionary")
do while ((Not p_Rs.eof))
set mybook = New DTO_clientes
MyBook.id = p_RS.fields("id").Value
MyBook.nome = p_RS.fields("nome").Value
m_lista.Add myBook.id, myBook
Rc= Rc + 1
p_RS.movenext
loop
end if
else
set m_lista = Server.CreateObject ("Scripting.Dictionary")
end if
End Function

end class

'DTOs
class DTO_clientes
private M_id
private M_nome

public Property Get id()
If Not IsNumeric(m_id) OR isEmpty(m_id) Then
id=null
Else
id=M_id
End If
end property
public Property Let id(x_id)
sTmp = x_id
If Not IsNumeric(sTmp) Then
sTmp = Null
Else
sTmp = CLng(sTmp)
End If
M_id=stmp
end Property

public Property Get nome()
sTmp = Trim(m_nome)
If Trim(sTmp) = "" Then sTmp = null
nome=stmp
end property
public Property Let nome(x_nome)
sTmp = Trim(x_nome)
If Trim(sTmp) = "" Then sTmp = Null
M_nome=stmp
end Property

end class

class Conexao
private StringConn
private m_conn

Public Property Get Conn()
set conn = m_conn
end Property

Public Property Let Conn(p_data)
Set m_conn = p_data
end Property

Sub Class_Initialize()

Set m_conn = Server.CreateObject ("ADODB.Connection")
StringConn = "driver={MySQL ODBC 3.51 driver};database=teste;user=root;password=;option=3 "

End Sub

Sub Class_Terminate()

Set m_conn = nothing

End Sub

Public Function StartTrans()
m_conn.BeginTrans
End Function

Public Function RollBackTrans()
m_conn.RollBackTrans
End Function

Public Function CommitTrans()
m_conn.commitTrans
End Function

Public Function CloseConn()
m_conn.Close()
End Function

Public Function OpenConn()
m_conn.Open StringConn
End Function

end class

Bem o que estas classes fazem?

Vamos analisar a classe Conexao primeiro. Esta classe é a conexão entre o banco de dados e os daos, ela possui os seguintes métodos:

. OpenConn() - Abre o objeto de conexão.

. CloseConn() - Fecha o objeto de conexão.

. StartTrans() - Inicia uma conexão com suporte a transação.

. CommitTrans() - Grava as alterações efetuadas no banco de dados em uma Conexão com transação.

. RollBackTrans() - Cancela as alterações efetuadas no banco de dados em uma conexão com transação.

Logo, temos a outra classe o DAO, conforme dito ele possui propriedades e métodos:

Propriedades:

. StartPage - Indica a página inicial dos dados, fornece suporte a paginação.

. MaxRows - Indica a quantidade de registros por página.

. RecordCount - Indica a quantidade de registros na tabela do banco. Esta propriedade e readonly não se pode alterar.

. OrderBy - Especifica a ordenação com que os dados devem vir da tabela.

Métodos:

. Find_All() - Retorna uma lista de objetos (DTO) com os registros do banco.

. FindbyWhere(filtro) - retorna uma lista de objetos (DTO) com os registros do banco, mas que atendam ao critério do filtro.

. FindbyID(key) - retorna uma lista de objetos (DTO) com os registros do banco, que tenha no banco a chave fornecida seria igual a um “where id=key”.

. Findbynome(key) - retorna uma lista de objetos (DTO) com os registros do banco, que tenha no banco a chave fornecida seria igual a um “where nome like key”.

. Insert(objeto) - insere um registro no banco, usando o objeto fornecido.

. Delete(key) - apaga um registro do banco, usando a chave fornecida.

. Update(objeto) - atualiza um registro usando um objeto fornecido.

A outra Classe é Clientes_DTO, responsável por representar um registro no banco de dados, vejamos os métodos que esta classe possui.

Métodos:

Id – Id da tabela clientes.

Nome – nome da tabela clientes.

Agora, com o modelo pronto, basta usar o seguinte código para inserir um registro no banco de dados.

‘ Cria o objeto de conexão e abre a conexão usando o método do objeto.

Set objconn = new conexao

Objconn.openconn()

‘ Cria o dao clientes para acesso às tabelas e inicializa a conexão no objeto.

Set daoclientes = new clientes_dao

Daoclientes.initialize(objconn.conn)

‘cria o novo cliente

Set novocliente = new dto_clientes

Novocliente.nome = “Carlos Alberto”

‘ I nsere o novo cliente no banco de dados e fecha a conexão

Daoclientes.insert(novocliente)

Objconn.closeconn()

Onde está a SQL? Embutida no código da classe. Desta forma, você passa a trabalhar apenas com objetos.

E para fazer a seleção? Basta usar o findall!

‘ Cria o objeto de conexão e abre a conexão usando o método do objeto.

Set objconn = new conexao

Objconn.openconn()

‘ Cria o dao clientes para acesso às tabelas e inicializa a conexão no objeto.

Set daoclientes = new clientes_dao

Daoclientes.initialize(objconn.conn)

‘ Seleciona todos os clientes do banco de dados e fecha a conexão

Set lista = Daoclientes.findall()

Objconn.closeconn()

For each item in lista.items

Response.write “codigo:” & item.id &”

Response.write “nome:” & item.nome &”

next

E para atualizar? Da mesma forma! Basta utilizar os objetos:

Set atualiza = new clientes_DTO

Atualiza.id=8

Atualiza.nome= “alberto roberto”

dao.update(atualiza)

Viram como fica fácil atualizar, editar, selecionar? Espero que tenham gostado! Logo postarei algo mais a respeito de classes em ASP.

Até a próxima