Acesso a Dados com Wizard (sem escrever código) e Programaticamente Base de Dados: loja.mdb Tabelas: Categorias (IdCat, NomeCat) Produtos (IdProd, IdCat, Preço, Stock) Carrinho (ProdId, Quantidade) Clientes (CliId, Nome, Morada, Telefone, NIF, BI) A – Visualização de uma tabela num controlo GridView através de Wizard 1. Criar um Web Site (File System Web site) File > New Web Site > ASP.NET Web Site Location: File System Visual C# OK. 2. Colocar a base de dados (loja.mdb) no directório App_Data Depois de colocada ver o conteúdo da Base de Dados: • duplo clique no ficheiro de base de dados (uso do Microsoft Access). • através do Server Explorer: na janela Server Explorer expandir Data Connections, loja.mdb, Tables. Surgem as tabelas Carrinho, Categorias, Clientes e Produtos. Para visualizar o conteúdo de uma tabela com o botão direito do rato em cima do nome da tabela seleccionar Show Table Data (pode ser necessário efectuar o Refresh). 3. Adicionar um Controlo GridView para mostrar os dados de uma Tabela Para mostrar os dados de uma tabela da base de dados num controlo GridView vamos criar: • uma ligação à base de dados • um controlo data source, que executa um comando SQL (Select) e retorna os resultados • um controlo GridView para carregar os dados do controlo data source e os mostrar Estes elementos podem ser adicionados separadamente. No entanto, o modo mais fácil é começar por adicionar um controlo GridView, e depois através de Wizards criar a ligação à base de dados e o objecto data source. Para posicionar o controlo GridView na página podemos começar por adicionar à página, em modo Design, uma tabela de 3 linhas por 3 colunas, fazendo: Layout > Insert Table Em seguida adicionámos à célula central da tabela (em modo Design) um controlo GridView (existente na ToolBox no grupo Data). Com o cursor em cima da GridView, clicámos na Smart Tag para obter o menu GridView Tasks. Seleccionar Choose Data Source:, e clicar em <New data source …>. Escolher como tipo de Data Source Access Database, e OK. Para seleccionar o ficheiro da base de dados premir Browse, seleccionar App_Data, seleccionar loja.mdb e OK. O campo de texto com o nome do ficheiro de base de dados fica preenchido com ~App_Data/loja.mdb. Premir Next. Para mostrar o conteúdo da tabela Categorias seleccionar: • Specify columns from a table or view, • nome da tabela: Categorias • colunas: * A instrução SQL mostrada será: Select * From [Categorias] Premir Next. Podemos testar a ligação à base de dados. Premir Finish. O Wizard • criou e configurou um controlo Access Data Source que incorpora a ligação à base de dados e a instrução SQL de interrogação especificada. • Ligou o controlo GridView ao controlo Access Data Source para que o controlo GridView mostre os dados retornados pelo controlo Access Data Source. 4. Testar a página: Premir Ctrl + F5 ou com o botão direito do rato em cima do nome da página seleccionar View in Browse. 5. Adicionar Paginação Na vista de Design clicar na Smart Tag, seleccionar Enable Paging. Testar e verificar que o controlo GridView apresenta um rodapé com links para números de páginas. Verificar a alteração do código na vista Source: AllowPaging="True". 6. Adicionar Ordenação Na vista de Design clicar na Smart Tag, seleccionar Enable Sorting. Testar e verificar que no controlo GridView os cabeçalhos das colunas mudaram para links. Verificar a alteração do código na vista Source: AllowSorting="True". 7. Esconder campos da tabela Para esconder a coluna com os valores de IdCat na vista de Design clicar na Smart Tag, seleccionar Edit Columns…, em Selected Fields seleccionar IdCat. Surgem as propriedades desta coluna (BoundField properties:). No grupo Behavior mudar a propriedade Visible de True para False. Testar e verificar. B – Criação de uma página Master-Detail através de Wizard com dois controlos GridView Nesta página vamos mostrar dados de duas tabelas relacionadas - tabela Categorias e tabela Produtos – e estabelecer entre elas uma relação master-detail, isto é, a tabela Produtos mostra apenas os produtos da categoria seleccionada na tabela Categorias. Para mostrar apenas os produtos da categoria seleccionada vamos criar um comando SQL parametrizado (instrução SELECT com cláusula WHERE). O controlo Access Data Source ligado à tabela dos Produtos conterá uma instrução SELECT com cláusula WHERE (filtro parametrizado): Select * From [Produtos] Where [IdCat] = ? O modo como este objecto (Access Data Source) vai buscar o valor do parâmetro é indicado noutro elemento que vai ser criado - elemento parameter. 1. Acrescentar uma página ao Web Site Na janela Solution Explorer, com o botão direito do rato em cima do nome do projecto, seleccionar Add New Item… seleccionar Web Form e mudar o nome da página para MasteDetailComWizard 2. Adicionar dois controlos GridView para estabelecer o relacionamento MasterDetail Para posicionar os controlos GridView na página podemos começar por adicionar à página, em modo Design, uma tabela de 2 linhas por 2 colunas, fazendo: Layout > Insert Table Rows: 2 Columns: 2 Na 1.ª linha da tabela colocámo dois Labels para os títulos “Categorias:” e “Produtos:”. Na 2.º linha colocámos dois controlos GridView, alterámos os IDs para gvCategorias (GridView para mostar as categorias) e gvProdutos (GridView para mostar as produtos). Através da Smart Tag do controlo gvCategorias criámos o objecto Access Data Source: GridView Tasks Choose Data Source: <New data source …> Access Database OK. Browse App_Data loja.mdb OK (~App_Data/loja.mdb) Next Specify columns from a table or view Categorias * (SELECT * FROM [Categorias]) Next Finish 3. Adicionar Selecção à GridView gvCategorias A tabela das Categorias vai funcionar como tabela Mestre. Para permitir seleccionar uma linha desta tabela, na vista de Design clicar na Smart Tag, e em GridView Tasks seleccionar Edit Columns. Debaixo de Available Fields abrir o nó Command Field, escolher Select e premir Add para o adicionar à lista dos SelectedFields. Estes procedimentos criam uma nova coluna da tabela com um CommandField Select. Através das propriedades deste Command Field é possível mudar a posição desta coluna, o tipo de botão (link, botão ou imagem), o texto, etc. Para que ao seleccionar uma linha desta tabela seja possível determinar a chave do respectivo registo é necessário seleccionar o controlo GridView, e na janela de propriedades colocar a propriedade DataKeyNames igual a IdCat. 4. Configuração da Instrução Select Parametrizada para mostrar os produtos associados à categoria seleccionada A tabela dos produtos vai funcionar como tabela de Detalhes mostrando os produtos da categoria seleccionada. É necessário uma instrução SQL diferente da anterior pelo será necessário um segundo objecto Access Data Source. Através da Smart Tag do controlo gvProdutos criámos o objecto Access Data Source: GridView Tasks Choose Data Source: <New data source …> Access Database OK. Browse App_Data loja.mdb OK (~App_Data/loja.mdb) Next Specify columns from a table or view Produtos * WHERE Column: IdCat Operator: = Source:Control Control ID: gvCategorias Default Value: 1 Add OK (SELECT * FROM [produtos] WHERE [IdCat] = ?) Next Finish 5. Testar a página Premir Ctrl + F5 ou com o botão direito do rato em cima do nome da página MasterDetailComWizard.aspx seleccionar View in Browse. C – Criação de uma página Master-Detail programaticamente (através de código) com dois controlos GridView Muitas aplicações Web são construídas usando múltiplas camadas, com um ou mais componentes para fornecer acesso aos dados. Vamos criar um objecto (classe DAL – Data Access Layer) para usar como fonte de dados para as nossas páginas Web. O modo de acesso aos dados de uma base de dados pode seguir um de dois modelos: • Arquitectura Ligada – usa o objecto DataReader para retornar os dados seleccionados. • Arquitectura Desligada – usa o objecto DataSet para receber os dados da base de dados. Vamos usar a arquitectura desligada – objecto DataReader. 1. Adicionar uma classe de Acesso a Dados (DAL) ao Web Site Na janela Solution Explorer, com o botão direito do rato em cima do nome do projecto, seleccionar Add New Item… seleccionar Class e mudar o nome da classe para DAL.cs. Visual Studio informa que a classe deve ser colocada no directório App_Code. Premir Yes. Como vamos usar objectos do namespace System.Data.OleDb devemos importar este package, acresecentando-o à lista dos packages já importados: using using using using using using using using using System; System.Data; System.Configuration; System.Web; System.Web.Security; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.WebControls.WebParts; System.Web.UI.HtmlControls; using System.Data.OleDb; public class DAL { private const string CONN = @"Provider=Microsoft.Jet.OLEDB.4.0;User ID=;"; private const string DBPATH = @"Data Source=|DataDirectory|/loja.mdb"; private OleDbConnection conn = null; private OleDbDataReader dr = null; public OleDbDataReader getCategorias() { conn = new OleDbConnection(); conn.ConnectionString = CONN + DBPATH; conn.Open(); string sqlStr = "Select * From Categorias"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = sqlStr; cmd.Connection = conn; dr = cmd.ExecuteReader(); return dr; } public void closeConnection() { dr.Close(); conn.Close(); } public OleDbDataReader getProdutosByIdCategoria(int codigo) { conn = new OleDbConnection(); conn.ConnectionString = CONN + DBPATH; conn.Open(); string sqlStr = "Select * From Produtos Where IdCat=?"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = sqlStr; cmd.Parameters.AddWithValue("IdCat", codigo); cmd.Connection = conn; dr = cmd.ExecuteReader(); return dr; } } 2. Acrescentar uma página ao Web Site Na janela Solution Explorer, com o botão direito do rato em cima do nome do projecto, seleccionar Add New Item… seleccionar Web Form e mudar o nome da página para MasteDetailEmCodigoComDataReader. De um modo semelhante à página anterior adicionar uma tabela com 2 linhas e 2 colunas, colocar na 1.º linha os títulos Categorias e Produtos e na 2.ª linha dois controlos GridView com os IDs gvCategorias (GridView para mostar as categorias) e gvProdutos (GridView para mostar as produtos). As fontes de dados destes controlos GridView serão colocadas programaticamente. A fonte de dados do controlo gvCategorias é colocada no método Page_Load da página. Este método é executado sempre que a página é chamada, quer seja a 1.ª vez, quer seja um postback. No entanto só é necessário carregar os dados da Base de Dados para o controlo GridView na 1.ª invocação da página. Depois, sempre que a página efectua um postback o controlo GridView mantém os dados. protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { DAL dal = new DAL(); gvCategorias.DataSource = dal.getCategorias(); gvCategorias.DataBind(); dal.closeConnection(); } } Para configurar as colunas do controlo GridView das Categorias: Seleccionar o controlo gvCategorias, premir o smart tag, seleccionar Edit Columns…, des-seleccionar Auto-generate fields, seleccionar BoundField para adicionar uma coluna ligada a um campo da tabela (campo NomeCat), e premir Add. Depois na lista dos Selected fields: ao seleccionar BoundField aparece a janela das suas propriedades (BoundField properties). Nesta janela, no grupo Data, em DataField colocar o valor NomeCat. Deste modo configurámos o controlo com apenas uma coluna ligada aos dados do campo NomeCat da tabela fonte de dados. Terminámos com OK. Em seguida devemos acrescentar mais uma coluna para permitir seleccionar uma linha desta tabela (procedimentos idênticos ao passo 3 da página anterior): clicar na Smart Tag, e em GridView Tasks seleccionar Edit Columns. Debaixo de Available Fields abrir o nó Command Field, escolher Select e premir Add para o adicionar à lista dos SelectedFields. Ainda, para que ao seleccionar uma linha desta tabela seja possível determinar a chave do respectivo registo é necessário seleccionar o controlo GridView, e na janela de propriedades colocar a propriedade DataKeyNames igual a IdCat. A fonte de dados do controlo gvProdutos é colocada no método que trata o evento resultante da selecção de uma linha da tabela das Categorias. Este método é executado sempre que o utilizador selecciona uma linha da tabela das Categorias. Um duplo clique num Select abre o respectivo método de tratamento de eventos, no ficheiro MasteDetailEmCodigoComDataReader.aspx.cs: protected void gvCategorias_SelectedIndexChanged(object sender, EventArgs e) { int idCat = (int)gvCategorias.SelectedDataKey.Value; DAL dal = new DAL(); gvProdutos.DataSource = dal.getProdutosByIdCategoria(idCat); gvProdutos.DataBind(); dal.closeConnection(); } 3. Testar a página Premir Ctrl + F5 ou com o botão direito do rato em cima do nome da página MasteDetailEmCodigoComDataReader.aspx seleccionar View in Browse. D – Actualizar, Inserir, e Apagar (Update, Insert and Delete) programaticamente com o controlo DetailsView Vamos exemplificar como actualizar, inserir ou remover registos de uma tabela (tabela produtos) usando o controlo Data-bound Web Server (Controlo Servidor Web ligado a dados) DetailsView. 1. Acrescentar uma página ao Web Site Add New Item… > Web Form e mudar o nome da página para ActualizarRegistos.aspx 2. Adicionar um controlo DetailsView Para posicionar o controlo DetailsView na página podemos começar por adicionar à página, em modo Design, uma tabela de 3 linhas por 3 colunas, fazendo: Layout > Insert Table Arrastar DetailsView Smart Tag > Edit Fields… Para cada campo da tabela Produtos efectuar o seguinte: em Available Fields: seleccionar BoundField e premir o botão Add para adicionar um campo aos Selected Fields. Este campo apresentará dados ligados a um campo da tabela. Para indicar qual o campo da tabela, nas propriedades do Bound Field, no grupo Data preencher a propriedade DataField. Para escolher uma designação para este campo no grupo Appearence preencher a propriedade Header Text: BoundField BoundField BoundField BoundField BoundField > Properties > Properties > Properties > Properties > Properties > > > > > DataField = IdProd; Header Text = Id do Produto DataField = IdCat; Header Text = Id da Categoria DataField = NomeProd; Header Text = Nome do Produto DataField = Preco; Header Text = Preço DataField = Stock; Header Text = Stock O Bound Field IdProd deve ter a propriedade do grupo Behavior InsertVisible a False para que em modo de inserção não pareça o campo IdProd. Para carregar os dados da tabela Produtos no controlo DetailsView colocar no método Page_Load o seguinte código: protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { preencherDetailsView(); } } private void preencherDetailsView() { DAL dal = new DAL(); DataSet ds = dal.getDataSetProdutos(); DetailsView1.DataSource = ds; DetailsView1.DataBind(); } Seleccionar o controlo DetailsView e configurar as seguintes propriedades: • No grupo Paging, AllowPaging a True. • No grupo Behavior, AutoGenerateDeleteButton, AutoGenerateEditButton, e AutoGenerateInsertButton a True, e AutoGenerateRows a False. • No grupo Data, DataKeyNames com o valor IdProd. Nas propridades do Controlo DetailsView seleccionar o separador Events, e no grupo Action efectuar duplo clique sobre PageIndexChanging, ItemDeleting, ItemInserting, ItemUpdating, e ModeChanging. O evento ModeChanging é desencadeado quando o controlo DetailsView tenta mudar entre o modo edit, insert ou read-only. A propriedade CurrentMode do controlo DetailsView pode ter 3 valores: • • • DetailsViewMode.Edit DetailsViewMode.Insert DetailsViewMode.ReadOnly O método ChangeMode() do controlo DetailsView permite mudar o seu modo. Colocar o seguinte código nos métodos de tratamento de eventos: protected void DetailsView1_PageIndexChanging(object sender, DetailsViewPageEventArgs e) { DetailsView1.PageIndex = e.NewPageIndex; preencherDetailsView(); } protected void DetailsView1_ItemDeleting(object sender, DetailsViewDeleteEventArgs e) { DAL dal = new DAL(); int idProd = Convert.ToInt32(DetailsView1.DataKey.Value); dal.deleteProduto(idProd); preencherDetailsView(); } protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e) { DAL dal = new DAL(); lerCamposDoRegisto(); dal.insertProduto(idCat, nome, preco, stock); DetailsView1.ChangeMode(DetailsViewMode.ReadOnly); preencherDetailsView(); } private private private private int idCat; string nome; double preco; int stock; private void lerCamposDoRegisto() { idCat = Convert.ToInt32( ((TextBox)DetailsView1.Rows[1].Cells[1].Controls[0]).Text); nome = ((TextBox)DetailsView1.Rows[2].Cells[1].Controls[0]).Text; preco = Convert.ToDouble( ((TextBox)DetailsView1.Rows[3].Cells[1].Controls[0]).Text); stock = Convert.ToInt32( ((TextBox)DetailsView1.Rows[4].Cells[1].Controls[0]).Text); } protected void DetailsView1_ItemUpdating(object sender, DetailsViewUpdateEventArgs e) { int idProd = Convert.ToInt32(DetailsView1.DataKey.Value); DAL dal = new DAL(); lerCamposDoRegisto(); dal.updateProduto(idProd, idCat, nome, preco, stock); DetailsView1.ChangeMode(DetailsViewMode.ReadOnly); preencherDetailsView(); } protected void DetailsView1_ModeChanging(object sender, DetailsViewModeEventArgs e) { if (e.NewMode == DetailsViewMode.Edit) DetailsView1.ChangeMode(DetailsViewMode.Edit); else if (DetailsView1.CurrentMode == DetailsViewMode.Edit && e.CancelingEdit) DetailsView1.ChangeMode(DetailsViewMode.ReadOnly); else if (e.NewMode == DetailsViewMode.Insert) DetailsView1.ChangeMode(DetailsViewMode.Insert); else if (DetailsView1.CurrentMode == DetailsViewMode.Insert && e.CancelingEdit) DetailsView1.ChangeMode(DetailsViewMode.ReadOnly); preencherDetailsView(); } Na classe DAL acrescentar o seguinte código: private void getConnection() { conn = new OleDbConnection(); conn.ConnectionString = CONN + DBPATH; conn.Open(); } public void closeConnection() { dr.Close(); conn.Close(); } public OleDbDataReader getCategorias() { getConnection(); string strSql = "Select * From Categorias"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = strSql; cmd.Connection = conn; dr = cmd.ExecuteReader(); return dr; } public OleDbDataReader getProdutosByIdCategoria(int codigo) { getConnection(); string strSql = "Select * From Produtos Where IdCat=?"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = strSql; cmd.Parameters.AddWithValue("IdCat", codigo); cmd.Connection = conn; dr = cmd.ExecuteReader(); return dr; } public DataSet getDataSetProdutos() { getConnection(); string strSql = "Select * From Produtos"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = strSql; cmd.Connection = conn; OleDbDataAdapter da = new OleDbDataAdapter(); da.SelectCommand = cmd; DataSet ds = new DataSet(); da.Fill(ds); return ds; } public int updateProduto(int idProd, int idCat, string nomeProd, double preco, int stock) { getConnection(); string strSql = "Update Produtos SET IdCat=? , NomeProd=? , Preco=? , Stock=? Where IdProd=?"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = strSql; cmd.Connection = conn; cmd.Parameters.AddWithValue("IdCat", idCat); cmd.Parameters.AddWithValue("nomeProd", nomeProd); cmd.Parameters.AddWithValue("preco", preco); cmd.Parameters.AddWithValue("stock", stock); cmd.Parameters.AddWithValue("idProd", idProd); int resultado = cmd.ExecuteNonQuery(); conn.Close(); return resultado; } public int insertProduto(int idCat, string nomeProd, double preco, int stock) { getConnection(); string strSql = "Insert Into Produtos (IdCat, NomeProd , Preco , Stock ) values (?,?,?,?)"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = strSql; cmd.Connection = conn; cmd.Parameters.AddWithValue("IdCat", idCat); cmd.Parameters.AddWithValue("nomeProd", nomeProd); cmd.Parameters.AddWithValue("preco", preco); cmd.Parameters.AddWithValue("stock", stock); } int idProd = cmd.ExecuteNonQuery(); conn.Close(); return idProd; public int deleteProduto(int idProd) { getConnection(); string strSql = "Delete From Produtos Where IdProd=?"; OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = strSql; cmd.Connection = conn; cmd.Parameters.AddWithValue("idProd", idProd); } int resultado = cmd.ExecuteNonQuery(); conn.Close(); return resultado; Para informação mais detalhada ver: Mostrar dados de uma base de dados Microsoft Access num controlo GridView: Walkthrough: Creating a Web Page to Display Access Database Data Mostrar dados de uma base de dados Microsoft SQL Server num controlo GridView com Ordenação e Paginação: Walkthrough: Basic Data Access in Web Pages Trabalhar com registos entre os quais exista uma relação master-detail: Walkthrough: Creating Master/Detail Web Pages in Visual Studio Editar e Inserir Registos: Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control Criar um componente de acesso a dados e usá-lo como fonte de dados numa página: Walkthrough: Data Binding to a Custom Business Object Tutorial 1: Creating a Data Access Layer Tutorial 1: Creating a Data Access Layer Tutorial 2: Creating a Business Logic Layer Tutorial 2: Creating a Business Logic Layer Tutorial 3: Master Pages and Site Navigation Tutorial 3: Master Pages and Site Navigation Tutorial 16: An Overview of Inserting, Updating, and Deleting Data Tutorial 16: An Overview of Inserting, Updating, and Deleting Data ASP.NET Quickstart Tutorials - Binding to Objects Binding to Objects