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:
Banco 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 |
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