Aplicação ReadWriteData
Aplicação com 1 página, que mostra num controlo DataGrid uma tabela de uma base de dados. O controlo DataGrid permite editar os valores mostrados nas células, e efectuar as correspondentes actualizações na base de dados. O modelo usado para ligação à base de dados é o modelo desligado, através de um DataSet e de um DataAdapter.
Para a construção da aplicação usa-se programação visual auxiliada por wizards. A construção do programa segue o “Walkthrough: Using a DataGrid Web Control to Read and Write Data”, existente no Help do Visual Studio.NET.
Base de Dados: loja.mdb
Tabela mostrada no controlo DataGrid: Produtos Campos da tabela Produtos: IdProd, NomeProd, Preco
O DataGrid usa a funcionalidade de paging apresentando apenas 10 linhas em cada página. Possui uma coluna com 2 botões, um para editar a linha (permitindo a edição de todas as células excepto a que contém a chave primária) e outro para apagar a linha (embora como não se deve apagar informação previamente guardada numa base de dados, deveria apenas alterar um campo da linha, fazendo o apagamento lógico e não físico. No entanto, a linha considerada logicamente apagada, não deveria ser mostrada no DataGrid. Para isso a selecção dos registos a mostrar no DataGrid deveria ter uma cláusula WHERE com a condição do campo apagado igual a false).
Notas:
1 – Acesso ao ficheiro da base de dados.
Como se usa uma base de dados Access é necessário dar acesso ao ficheiro. No explorer, com o botão direito do rato em cima do ficheiro, seleccionar Security.
Adicionar o utilizador ASPNET do w2ks com full control. Os computadores existentes nos laboratórios pertencem ao domínio, existindo o utilizador ASPNET. Nos outros computadores (que não pertencem ao domínio), não existe o utlizador ASPNET. Nesses é necessário dar full control aos 2 utilizadores (internet guest account – conta de
convidado da internet, e everyone - todos) quer para o ficheiro da base de dados, quer para o directório no qual ele está contido.
No windows XP para permitir a utilização de segurança, é necessário seleccionar o menu tools de uma pasta (ou do windows explorer), escolher “Folder Options”, e no separador View (Ver), na lista de Advanced settings (Definições avançadas) retirar a verificação (des-seleccionar o check box) da opção “Use simple file sharing” (Utilizar partilha de ficheiros simples - Recomendado).
2 – Ligação à base de dados efectuada pelo Visual Studio
Se se usa o wizard do Visual Studio para a geração da string de conexão, deve proceder-se do proceder-seguinte modo:
- para a geração da string de conexão deve-se indicar um caminho para a base de dados acesível da nossa conta, por ex., W:\ReadWriteData\loja.mdb (se for W a letra do drive que mapeia o w2ks);
- para a execução da página, quem executa é a conta ASPNET, e para esta conta, o caminho W: não faz sentido (não existe este drive).
Portanto temos que mudar manualmente a string de conexão, no código gerado automaticamente pelo wizard, no método InializeComponent, substituindo
W:\ReadWriteData\loja.mdb por C:\Inetpub\wwwroot\XXX\loja.mdb, em que XXX é o nome do directório virtual (ex. 900330 para os alunos e moutaw para os docentes). 3 – Caso no acesso à BD surja a excepção Ficheiro já em uso.
Verificar se o ficheiro mdb não está aberto pelo Access ou pelo Visual Studio.NET. Para verificar se está aberto pelo Visual Studio.NET fazer View, Server Explorer e verificar as conexões existentes e o respectivo estado. Se alguma conexão estiver ligada, pode-se desligar. Se se pretender ligar, seleccionar Refresh.
Esta excepção pode aparecer se noutra função da mesma página, a ligação à base de dados foi aberta mas não fechada. Deve-se corrigir e fechar sempre as ligações à base de dados.
4 – Caso no acesso à BD surja a excepção Impossibilidade de fazer lock.
Modificar a string de conexão gerada automaticamete pelo Visual studio, retirando a parte “Mode=Share Denny None” e “DataBase Locking Mode”. Alternativamente substituir toda a string de conexão pela string usada em exercícios anteriores.
Construção do programa:
1. Criar a página Formulário Web com os componentes data necessários e o controlo DataGrid para mostrar os dados.
2. Adicionar código para ler os dados da base de dados e ligar os dados ao controlo DataGrid.
3. Configurar o controlo DataGrid para permitir edição dos dados. 4. Adicionar código para actualização dos dados.
Funcionamento do programa: Mostrar:
Actualizar:
Passo 1: Criar componentes data e o controlo DataGrid
Divide-se em 2 acções:
- Criar o data adapter. O data adapter contém instruções SQL para ler e escrever informação para a base de dados.
- Gerar o esquema do dataset definindo as tabelas e colunas constituintes. O Visual Studio criará uma classe dataset e adicionará uma instância ao formulário.
Dados na Base de Dados
Procedimentos:
A. Criar os objectos Connection e DataAdapter
- Criar um novo Projecto designado ReadWriteData
- Incluir a base de dados no Projecto: Add > Add Existing Item loja.mdb - Alterar permissões de acesso à base de dados ... (Ver as Notas descritas atrás) - Criar o objecto DataAdapter:
Toolbox > tabulador Data > arrastar OleDbDataAdapter
Surge o wizard. Permite especificar o objecto Connection e os Comandos a executar na base de dados que o DataAdapter irá usar.
Next > New Connection
Fornecedor: Microsoft Jet 4.0 OLE DB Provider Seguinte
1. Nome da base de dados ... Procurar loja.mdb debaixo de ReadWriteData 2. Nome do utilizador Admin
3. Testar a Ligação OK
Mudar manualmente a string de conexão ... (Ver as Notas descritas atrás) Next Use SQL Statements
Next What data should the data adapter load into the dataset? Select * From Produtos ou através do Query Builder Don´t include password
The data adapter oleDbDataAdapter was configured successfuly. Generated SELECT, INSERT, UPDATE e DELETE Statements. Generated table mappings.
Finish
Surgem no Page 2 objectos: oleDbDataAdapter e oleDbDataConnection
B. Criar o DataSet
Visual Studio vai gerar o dataset automaticamente baseado na instrução Select especificada no data adapter. Primeiro cria uma classe DataSet (ficheiro .xsd) que descreve os elementos do dataset (tabelas, colunas e restrições) e em seguida cria uma instância.
Procedimentos:
Botão direito do rato no oleDbDataAdapter Seleccionar Generate DataSet
New: DataSet1 (nome da classe criada) Choose which table to add to the dataset Ok
Clicar Show All Files: ficam visíveis os ficheiros DataSet1.xsd e DataSet1.cs com as definições do schema e da classe que definem o dataset.
C. Criar o DataGrid
Toolbox > Web Forms > arrastar DataGrid AutoFormat: Professional1
Property Builder: (General)
DataSource: DataSet11 – nome do dataset para ligar ao datagrid DataMember: Produtos – nome da tabela do dataset para ser visualizada Data Key Field: IdProd - chave primária para os registos da tab. Produtos. Ok.
O controlo DataGrid já está ligado ao dataset, mas o dataset não é carregado automaticamente.
Passo 2: Adicionar código para ligar os dados ao controlo DataGrid.
No método Page_Load colocar:
private void Page_Load(object sender, System.EventArgs e) {
// Put user code to initialize the page here oleDbDataAdapter1.Fill(dataSet11);
if (!Page.IsPostBack )
DataGrid1.DataBind(); }
Passo 3: Configurar o controlo DataGrid para permitir edição dos dados.
Para permitir editar linhas do datagrid adicionar um botão Edit a cada linha da grelha. A activação do botão alterará os componentes da linha, passando os campos editáveis para text boxes, e o botão Edit será substituído por 2 botões Update e Cancel.
Procedimentos: Property Builder Columns
Available Columns
+ Button Column
Seleccionar Edit, Update e Cancel Button type = Push Button (Link Button)
Adicionar ( > ) para adicionar os botões à caixa de colunas seleccionadas.
Ok.
Criação do código de tratamento de eventos para colocar linhas no modo de edição O controlo DataGrid possui a capacidade de colocar linhas no modo de edição através da propriedade EditItemIndex. Para colocar uma linha em modo de edição coloca-se o
valor da propriedade com o índice dessa linha (as linhas começam por zero), e para voltar ao modo normal coloca-se o valor da propriedade a -1.
Exemplo:
Colocar a terceira linha do DataGrid1 em modo de edição: DataGrid1.EditItemIndex = 2;
Colocar o DataGrid1 em modo normal de visualizção: DataGrid1.EditItemIndex = -1;
Procedimentos:
Propriedades do controlo DataGrid1 Seleccionar o botão Events
Duplo clique em EditCommand Duplo clique em CancelCommand Duplo clique em UpdateCommand
Colocar o seguinte código:
No tratamento de eventos EditCommand
private void DataGrid1_EditCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e) {
DataGrid1.EditItemIndex = e.Item.ItemIndex; DataGrid1.DataBind();
}
No tratamento de eventos CancelCommand
private void DataGrid1_CancelCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e) {
DataGrid1.EditItemIndex = -1; DataGrid1.DataBind(); }
Testar a parte da aplicação já construída. O controlo DataGrid deve mostrar os dados do dataset, o qual contém dados extraídos da base de dados. Testar a capacidade de edição de linhas.
Passo 4: Adicionar código para actualização dos dados na base de dados
O botão Update deve desencadear as seguintes acções.
1. Determinar que linha do controlo DataGrid foi actualizada. Obter o valor da chave dessa linha.
3. Encontrar a linha do dataset com o mesmo valor da chave e escrever as mudanças para essa linha. Está actualizado o dataset mas ainda não está actualizada a base de dados.
4. Executar o comando SQL que envia as mudanças do dataset para a base de dados.
5. Refrescar o conteúdo do controlo DataGrid (com os dados do dataset).
Ponto 1.
Quando o botão é activado, o objecto evento passado como argumento tem uma propriedade Item que é o objecto que representa a linha do controlo DataGrid. Este objecto Item tem uma propriedade ItemIndex com o índice da linha.
O controlo DataGrid tem uma propriedade DataKeys com a colecção de chaves da tabela. Através do índice da linha determina-se a chave dessa linha.
string key = DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
Ponto 2.
A propriedade Item do objecto evento (que representa a linha) tem uma propriedade
Cells, com a colecção de células dessa linha. Cada célula tem uma propriedade Controls, com os controlos de cada célula (muitas vezes existe apenas 1 controlo em
cada célula -- Controls[0] – mas uma célula pode conter mais que um controlo). Código para obter os valores dos controlos editáveis das células da linha:
TextBox Tb = (TextBox)(e.Item.Cells[1].Controls[0]); string NomeProduto = Tb.Text;
Tb = (TextBox)(e.Item.Cells[2].Controls[0]); string PrecoProduto = Tb.Text;
Ponto 3.
Encontra a linha da tabela do dataset correspondente à linha que o utilizador actualizou no datagrid.
O método FindBy<nome_do_campo_chave> invocado com o valor da chave como argumento, retorna uma referência para a linha.
DataSet1.ProdutosRow r =
dataSet11.Produtos.FindByIdProd(int.Parse(key));
Escreve as mudanças actualizando a tabela do dataset.
r.NomeProd = NomeProduto;
r.Preco = int.Parse(PrecoProduto);
Notas:
Se a tabela Produtos da base de dados loja.mdb não tem apenas uma chave IdProd, mas possui duas chaves IdProd e IdCat, o método FindByIdProd não existe (existirá o método FindByIdProdIdCat(-,-).
Alternativas:
- Ao criar o DataAdapter na instrução Select não incluir todos os campos da tabela Produtos (excluir o campo IdCat). Deste modo o dataset já não contém o campo IdCat. Ou - Alterar na base de dados a tabela Produtos de modo a ter uma única chave IdProd. Depois apagar o dataset e gerar um novo dataset a partir da base de dados (ou mantendo o dataset já gerado, alterar o schema apagando as chaves e criando apenas uma).
Ponto 4.
Executa o comando SQL que envia as mudanças do dataset para a base de dados.
oleDbDataAdapter1.Update(dataSet11);
Termina o modo de edição do DataGrid.
DataGrid1.EditItemIndex = -1;
Ponto 5.
Refrescar o conteúdo do controlo DataGrid (com os dados do dataset).
DataGrid1.DataBind();
Em seguida mostra-se o código completo a incluir no método de tratamento de eventos UpdateCommand:
private void DataGrid1_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e) {
// Obtem os valores do campo chave da linha actualizada
string key = DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
// Obtem os valores dos controlos (textboxes) que o utiliz. actual. // As colunas do DataGrid são expostas na colecção Cells.
// Cada célula tem uma colecção de controlos.
// Neste caso, só há um controlo em cada célula – um TextBox. // Ler o valor do TextBox através da propriedade Text
// para uma variável local (é necessário casting). //
// A 1.ª coluna -- Cells(0) – contém os botões Update e Cancel.
// Obtem o valor do controlo TextBox control na 2.ª coluna TextBox Tb = (TextBox)(e.Item.Cells[1].Controls[0]);
string NomeProduto = Tb.Text;
// Obtem o valor do controlo TextBox control na 3.ª coluna Tb = (TextBox)(e.Item.Cells[2].Controls[0]);
string PrecoProduto = Tb.Text;
// Encontra a linha da tabela do dataset correspondente à // linha que o utilizador actualizou no datagrid.
// O método FindBy<nome_do_campo_chave> invocado com o valor // da chave como argumento, retorna uma referência para a linha.
DataSet1.ProdutosRow r =
dataSet11.Produtos.FindByIdProd(int.Parse(key));
// Actualiza a tabela do dataset. r.NomeProd = NomeProduto;
r.Preco = int.Parse(PrecoProduto);
// Executa a instrução SQL para actualizar a bd a partir do dataset oleDbDataAdapter1.Update(dataSet11);
// Termina o modo de edição do DataGrid DataGrid1.EditItemIndex = -1; // Refresca o DataGrid DataGrid1.DataBind(); } Testar a aplicação.
Vamos fazer ainda as seguintes alterações: 1. Retirar a coluna IdCat;
2. Adicionar nova coluna de botões Delete;
3. Colocar o campo ProdId não editável, porque é a chave da tabela; 4. Configurar o controlo datagrid para efectuar paginação.
Pontos 1 e 2:
O controlo DataGrid permite escolher as colunas específicas a serem mostradas, mudar a posição relativa, mudar os cabeçalhos, etc. Para retirar a coluna IdCat e adicionar uma nova coluna com botões seleccionar o controlo DataGrid1:
Property Builder (surge a janela DataGrid1 Properties) Separador Columns
Retirar a selecção em “Create columns automatically at run time” Na área Selected Columns já existe a coluna Edit, Update e Cancel.
Em Available Columns seleccionar:
- a coluna IdProd e adicionar (>) à área Selected Columns. - a coluna NomeProd e adicionar (>) à área Selected Columns. - a coluna Preco e adicionar (>) à área Selected Columns.
Expandir Button Column e seleccionar Edit e adicionar (>) à área Selected Columns. Na área Selected Columns seleccionar Delete e premir o botao à direita com a seta ascendente para posicionar a coluna Delete em 2.º lugar. Deste modo determinámos os posicionamentos relativos das colunas.
Ponto 3.
Na área Selected Columns seleccionar a coluna IdProd e colocar um visto no checkbox Read-only. Deste modo ao colocar a linha no modo editável este campo permanece não editável.
Ponto 4.
Para configurar o controlo Datagrid para mostrar uma página de cada vez: Seleccionar o controlo DataGrid1:
Property Builder (surge a janela DataGrid1 Properties) Separador Paging
Seleccionar o check box Allow paging
Colocar o tamanho da página (Page size)
Seleccionar o check box Show navigation buttons e definir a posição e modo
para os botões de navegação. Clicar Apply e depois OK.
Para que na página “code-behind” surja o método de tratamento de eventos
PageIndexChanged, seleccione o botão Events nas Propriedades do controlo DataGrid1, e faça duplo clique em PageIndexChanged. Coloque o seguinte código no método criado:
private void DataGrid1_PageIndexChanged(object source,
System.Web.UI.WebControls.DataGridPageChangedEventArgs e) {
DataGrid1.CurrentPageIndex = e.NewPageIndex; DataGrid1.DataBind();
}
Finalmente grave as mudanças, construa o projecto (Build Project) porque foi adicionado código, e veja a página no browser (View in browser) para testar a funcionalidade de paginação.