INTRODUÇÃO AO MODELO ADO.NET (DESCONECTADO)
O modelo ADO.NET (Activex Data Objects .NET) consiste num conjunto de classes
definidas pela .NET framework (localizadas no namespace System.Data) que pode ser
utilizado para aceder aos dados armazenados numa base de dados remota.
A seguir apresentam-se os principais objectos do “modelo desconectado” ADO.NET.
Dataset
Data Table
.NET Data Provider
Data Adapter
Command
Servidor de BD
Connection
BD
O “modelo desconectado” ADO.NET utiliza dois tipos de objectos para aceder à base
de dados: os objectos Dataset, que podem conter um ou mais objectos Data Table, e os
objectos .NET Data Provider.
Um Data Provider representa um conjunto de componentes (DataAdapter, DataReader,
Command e Connection) que permite estabelecer a ligação a uma fonte de dados,
executar comandos (SQL) e devolver o seu resultado.
O objecto Connection possibilita a ligação a uma fonte de dados.
O objecto Command permite aceder e manipular a base de dados (representa um
comando SQL).
O objecto Data Reader permite acesso só de leitura e sequencial à base de dados.
O objecto Data Adapter serve de ponte entre a base de dados e o objecto Dataset. Para
tal, o objecto Data Adapter utiliza objectos Command para executar instruções SQL na
base de dados.
O objecto Dataset contém um ou mais objectos Data Table. Assim, os dados que vão
“alimentar” a aplicação estão armazenados neste objecto.
O modelo ADO.NET permite trabalhar com cenários conectados e desconectados,
embora tenha sido construído a pensar, essencialmente, numa arquitectura
desconectada.
De modo simplista, no cenário conectado existe permanentemente uma ligação activa à
base de dados enquanto os dados são manipulados. O anterior modelo ADO foi pensado
para uma arquitectura deste género, apesar de também permitir recorrer à técnica
conhecida como disconnected recordset.
Basicamente, no modelo desconectado, o objecto Data Adapter utiliza um objecto
Command para executar uma instrução SQL (tipicamente um comando Select) para
obter os dados. O objecto Command utiliza um objecto Connection para estabelecer
uma ligação com a base de dados e obter os dados pretendidos. Depois, o objecto Data
Adapter armazena os dados num objecto Data Table do Objecto Dataset.
Note-se que, no modelo desconectado, a ligação à base de dados apenas permanece
aberta durante o tempo necessário para obter ou alterar os dados da base de dados.
Depois, essa ligação é fechada e a aplicação trabalha com “a cópia” dos dados através
do objecto Dataset. Portanto, os dados armazenados no Dataset são independentes dos
dados registados na base de dados.
Todavia, as alterações realizadas sobre os dados existentes no Dataset são
posteriormente reflectidas na base de dados. Para actualizar a base de dados com as
alterações efectuadas sobre o Dataset, o objecto Data Adapter utiliza um objecto
Command que define um comando Insert, Update ou Delete. Depois, o objecto
Command usa um objecto Connection para estabelecer uma ligação com a base de
dados e executar a instrução de actualização. Posteriormente, a ligação é fechada.
ADO.NET DATA PROVIDERS
Todos os objectos do modelo ADO.NET são implementados por classes definidas no
espaço de nomes (namespace) System.Data da .NET framework. Contudo, as classes
específicas utilizadas para implementar os objectos Data Adapter, Command e
Connection dependem do Data Provider que é utilizado.
Actualmente, a .NET framework inclui quatro Data Providers: o SQL Server Data
Provider, que foi desenhado para providenciar acesso a servidores SQL Server, o OLE
DB Data Provider, que permite aceder a qualquer motor de base de dados que suporte o
interface OLE DB, o ODBC .NET Data Provider, que permite aceder a fontes de dados
através de ODBC, e o .NET Data Provider for Oracle, que permite o acesso a bases de
dados Oracle.
Adicionalmente a estes quatro Data Providers, existem outros que foram desenvolvidos
pelos fabricantes, para permitirem um acesso optimizado às suas bases de dados. Por
exemplo, existem Data Providers específicos para servidores MySQL, SQL Anywhere,
etc.
Para se poder utilizar um .NET Data Provider, deve-se adicionar, no início do ficheiro,
uma instrução de Import para o espaço de nomes apropriado. Caso contrário, tem que se
qualificar cada classe que se refira a estes espaços de nomes, dado que estes espaços de
nomes não são incluídos, por defeito, como referências. Por exemplo, para utilizar o
OLE DB Data Provider pode-se utilizar o seguinte código:
Imports System.Data.OleDb
.
.
Dim cnAlunos As New OleDbConnection()
Ao não utilizar a instrução de Import teria que usar o seguinte código:
Dim cnAlunos As New OleDb.OleDbConnection()
As principais classes incluídas no OLE DB Data Provider são: OleDbConnection,
OleDbCommand, OleDbDataReader e OleDbDataAdapter. A seguir, apresentam-se,
resumidamente, as suas principais propriedades e métodos.
Classe OleDbConnection
Propriedades
Descrição
ConnectionString Contém informação que permite estabelecer a ligação a uma base
de dados (nome do servidor, nome da base de dados, informação
de login).
Métodos
Descrição
Open
Abre uma ligação com uma base de dados.
Close
Fecha uma ligação com uma base de dados.
Notas:
A utilização de um objecto connection passa pela definição de uma string de ligação;
pela criação do objecto connection; pela abertura da ligação e pelo fecho da ligação.
Existem, essencialmente, duas formas de criar um objecto connection a partir do
VS.NET: em design time e em run time. Em design time, ou seja, antes da execução do
código, existem alguns wizards que nos auxiliam na sua criação (DataAdapter
Configuration Wizard, Server Explorer, etc.). Em run time, podemos criar um objecto
connection do seguinte modo:
Imports System.Data.OleDbClient
.
.Dim con As New OleDbConnection()
Dim constring As String
constring = "Provider=""MSDAORA.1""; User ID=abd1; Data Source=arturdb;
Password=abd1"
Con.ConnectionString = constring
Con.Open
.
Con.Close
Após a utilização de um objecto connection é extremamente importante que o mesmo
seja fechado, pois libertará recursos não só do lado do cliente, como também, e
sobretudo, do lado do servidor, melhorando assim o desempenho da aplicação. Caso o
objecto connection não seja fechado de forma explícita, o garbage collector do VS.NET
vai depois tratar da libertação dos respectivos recursos, assim que uma variável saia do
seu âmbito (scope).
Todavia, não será prejudicial ao desempenho de uma aplicação a abertura e fecho
sistemático de uma ligação à base de dados?
Se o objectivo for a criação de uma aplicação para meia dúzia de utilizadores em
simultâneo, então certamente que uma boa prática será a criação da ligação à base de
dados assim que a aplicação inicia e o seu fecho assim que a aplicação termina.
Por outro lado, se a aplicação for construída para funcionar em ambiente distribuído
para centenas ou milhares de utilizadores, então a ligação à base de dados deve ser
libertada o mais cedo possível.
Note-se que, na prática, ao invocar o método close(), estaremos apenas fazer uma
desactivação da ligação à base de dados, para minimizar os recursos utilizados, à espera
que seja invocada uma nova ligação com as mesmas características, para reactivar essa
ligação (em vez de criar uma nova). A este processo dá-se, vulgarmente, o nome de
connection pooling (o aspecto chave a reter será manter a mesma connection string).
Classe OleDbCommand
Propriedades
Connection
Descrição
O objecto OleDbConnection que é utilizado, pelo objecto
command, para estabelecer a ligação à base de dados.
CommandText
Comando SQL, nome de um procedimento armazenado ou o
nome de uma tabela.
CommandType
Uma constante que indica se a propriedade CommandText contém
um comando SQL (Text), o nome de um procedimento
armazenado (StoredProcedure), ou o nome de uma tabela
(TableDirect).
Parameters
A colecção de parâmetros do objecto Command.
Métodos
Descrição
ExecuteReader
Executa uma consulta e devolve o resultado na forma de um
objecto OleDbDataReader. Por outras palavras, retorna uma
referência a um objecto OleDbDataReader que conterá um
conjunto de registos devolvidos da base de dados. Para tal, deverse-á atribuir a execução deste método a uma variável do tipo
OleDbDataReader.
ExecuteScalar
Executa a consulta e devolve, por exemplo, o valor da (primeira)
coluna do (primeiro) registo.
ExecuteNonQuery Executa o comando e devolve um inteiro que indica o número de
registos afectados (aconselhado para utilizar com comandos
Insert, Update e Delete).
Notas:
Quando se utiliza um objecto Data Adapter, a ligação à base de dados é aberta e
fechada de forma automática. Porém, se a ligação já se encontrar aberta, terá de ser
fechada manualmente.
É também possível utilizar os métodos do objecto Data Adapter para executar as
instruções SQL do objecto Command.
Tal como no caso do objecto connection, também um objecto command pode ser criado
em design time, através de um DataAdapter Configuration Wizard ou do Server
Explorer, e em run time, do seguinte modo:
.
.
Dim con As New OleDbConnection()
Dim constring As String
Dim cmd As New OleDbCommand()
Dim rdr As New OleDbDataReader
.
.
cmd.Connection = con
cmd.CommandText = “Select nome, morada From Clientes”
cmd.CommandType = CommandType.Text
rdr = cmd.ExecuteReader (CommandBehavior.CloseConnection)
.
.
Resumindo, o primeiro passo a realizar após a criação de um objecto command será
associar-lhe um objecto connection. Depois, deve-se indicar o comando (SQL) a
executar e o seu tipo.
Note-se que, no método Executereader, podemos indicar, através de um parâmetro (com
a instrução CommandBehavior.CloseConnection), que se pretende fechar
automaticamente a ligação assim que é devolvida a referência ao objecto
OleDbDataReader.
Classe OleDbDataAdapter
Propriedades
SelectCommand
DeleteCommand
InsertCommand
UpdateCommand
Métodos
Fill
Update
Descrição
Objecto OleDbCommand que inclui uma instrução Select para
consultar a base da dados.
Objecto OleDbCommand que inclui uma instrução Delete para
eliminar registos da base da dados.
Objecto OleDbCommand que inclui uma instrução Insert para
adicionar registos à base da dados
Objecto OleDbCommand que inclui uma instrução Update para
alterar registos da base de dados
Descrição
Executa o objecto Command identificado pela propriedade
SelectCommand e regista o resultado num objecto Dataset.
Executa os objectos Command identificados pelas propriedades
DeleteCommand, InsertCommand e UpdateCommand, por cada
registo do Dataset que tenha sido eliminado, inserido ou alterado.
(ver método HasChanges do objecto DataSet. Este método vai
verificar a propriedade RowState (Added, Deleted, Modified,
Unchanged) de cada registo do DataSet para verificar se foram
efectuadas alterações ao DataSet)
Notas: Quando é usado o método Fill para obter dados da base de dados, o objecto Data
Adapter utiliza um objecto Data Reader para ler os registos do resultado devolvido pela
consulta e armazenar esses registos num objecto Dataset. Depois, a aplicação pode
trabalhar com os dados do Dataset sem afectar os dados da base de dados.
Porém, se a aplicação efectuar alterações aos dados do Dataset, pode ser utilizado o
método Update do objecto Data Adapter para executar os objectos Command
identificados pelas propriedades DeleteCommand, InsertCommand e UpdateCommand
para registar essas alterações na base de dados.
Quando é executado o método Update é aberta automaticamente uma ligação. Essa
ligação é também fechada automaticamente quando a actualização for concluída.
Um objecto Data Adapter pode ser criado em design time, através de um DataAdapter
Configuration Wizard ou do Server Explorer, e em run time, do seguinte modo:
.
.
Dim dad As New OleDbDataAdapter()
Dim con As New OleDbConnection()
Dim cmd As New OleDbCommand()
Dim ds As New OleDbDataset()
Dim constring As String
.
.
cmd.Connection = con
cmd.CommandText = “Select nome, morada From Clientes”
cmd.CommandType = CommandType.Text
dad.SelectCommand = cmd
dad.fill(ds, “Clientes”)
‘2.º arg (não obrig.)Æ nome da data table do dataset ds
.
.
No código anterior os objectos Command e Connection foram criados explicitamente e
só depois foram associados ao objecto DataAdapter. Porém, existe ainda a possibilidade
de indicar implicitamente qual a instrução Select e qual a ligação à base de dados a
utilizar pelo objecto DataAdapter:
.
.
From Clientes”,
Dim dad As New OleDbDataAdapter(“Select nome, morada
"Provider=""MSDAORA.1""; User ID=abd1; Data Source=arturdb; Password=abd1")
A grande vantagem de utilizar este método reside no facto de a criação e a destruição
dos objectos Command e Connection ser gerida pelo próprio Data Adapter. O primeiro
método é sobretudo aconselhável em situações de reutilização dos objectos em questão.
Classe OleDbDataReader
Propriedades
Item
FieldCount
Métodos
Read
Close
Descrição
Acede à coluna com o índice ou nome especificado do registo
actual.
Número de colunas do registo actual.
Descrição
Lê o próximo registo. Devolve True se existirem mais registos.
Caso contrário, devolve False.
Fecha o objecto Data Reader.
Note-se que o objecto Data Reader permite ler dados da base de dados, mas não permite
modificá-los. Por outras palavras o Data Reader é um objecto só de leitura. Por outro
lado, ele só permite uma leitura sequencial, isto é, mal se aceda a um registo, o registo
anterior passa a estar inacessível. O objecto Data Reader só pode ser criado a partir de
um objecto Command:
Dim cmd As New OleDbCommand()
Dim rdr As New OleDbDataReader
rdr = cmd.ExecuteReader
While (rdr.read())
.
.
End While
rdr.close
Note-se ainda que os nomes das classes do .NET OLE DB Data Provider têm o prefixo
OleDB.
Classe Dataset
Um objecto Dataset consiste num repositório de dados em memória, no lado do cliente,
e apresenta-se como o principal representante do conjunto de objectos do modelo
ADO.NET a suportar a arquitectura desconectada.
Um objecto Dataset nada sabe acerca da fonte de dados de onde provêm os seus dados,
podendo estes provirem de diferentes bases de dados. Isto acontece porque, o objecto
Data Adapter serve de ponte entre o DataSet e a base de dados, pois utiliza a
informação de como ligar e aceder à base de dados (a partir dos objectos connection e
command), ao mesmo tempo que proporciona métodos para preencher o DataSet de
dados, assim como para efectivar a alteração dos dados, realizada ao nível do DataSet,
na fonte de dados.
Um objecto Dataset consiste numa hierarquia de um ou mais objectos Data Table e
Data Relation.
Um objecto Data Table consiste de um ou mais objectos Data Column, Data Row e
Constraint.
Um objecto Data Relation define o modo como as tabelas de um objecto Dataset estão
relacionadas. O objecto Data Relation é essencialmente utilizado para gerir as restrições
e, desse modo, simplificar a navegação entre tabelas relacionadas.
Os objectos Data Column definem os dados em cada coluna da tabela, incluindo o seu
nome, tipo de dados, etc.
Os objectos Data Row contêm os dados para cada registo da tabela.
Os objectos Constraint são utilizados para manter a integridade dos dados. Uma
restrição de chave primária assegura que os valores numa coluna, tal como a coluna de
chave primária, são únicos. Uma restrição de chave forasteira determina como os
registos de uma tabela são afectados quando os registos correspondentes duma tabela
relacionada são alterados ou eliminados.
Note-se que todos os objectos de um Dataset são armazenados em colecções. Por
exemplo, os objectos Data Table são armazenados numa colecção de objectos Data
Table, e os objectos Data Row são armazenados numa colecção de objectos Data Row.
Pode-se aceder a estas colecções através das propriedades dos respectivos objectos.
Download

O modelo ADO.NET