Shop Notas de implementação (continuação) Em Resumo 1. 2. 3. 4. 5. 6. Criar o componente ShopClassLibrary com os diversos serviços de Acesso a Dados (implememtar todos os serviços) Criar um Web Site que será cliente do componente ShopClassLibrary Porque o Web Site vai utilizar serviços do componente é preciso adicionar ao Web Site uma referência ao componente No Web Site criado, no directório App_Data, adicionar a BD existente sales.mdb Atendendo ao pathname da BD actualizar no componente o valor da string de conexão à BD Criar as várias WebForms constituintes do site 1 Implementar na classe Customer o método public DataSet GetByID(string user, string pass, int clientID) { OleDbConnection conn = null; DataSet ds = null; try { // criar objecto de conexão à base de dados e abrir a conexão conn = new OleDbConnection(UtilDB.CONN); conn.Open(); // validar utilizador if (UtilDB.ValidateUser(conn, null, user, pass) !=ShopStatusEnum.OK) return null; // efectuar pesquisa ds = UtilDB.GetByID(conn, null, “Customers", “CustomerID", clientID); } catch (OleDbException ) { // tratar a excepção!!!! ….. } finally { // fechar a conexão if (conn.State == ConnectionState.Open) conn.Close(); } return ds; } 2 Implementar na classe Customer o método public DataSet FindByName (string user, string pass, string name) { OleDbConnection conn = null; DataSet ds = null; try { // criar objecto de conexão à base de dados e abrir a conexão conn = new OleDbConnection(UtilDB.CONN); conn.Open(); // validar utilizador if (UtilDB.ValidateUser(conn, null, user, pass) !=ShopStatusEnum.OK) return null; // efectuar pesquisa ds = UtilDB.FindByStringField(conn, "Customers", "Name", name); } catch (OleDbException ) { // tratar a excepção!!!! ….. } finally { // fechar a conexão if (conn.State == ConnectionState.Open) conn.Close(); } return ds; } 3 static public DataSet FindByStringField(string table, string field, string key) { OleDbConnection conn = null; DataSet ret = new DataSet(); try { // criar objecto de conexão à base de dados conn = new OleDbConnection(UtilDB.CONN); // invocar método auxiliar ret = FindByStringField(conn, table, field, key); } catch (OleDbException ex) { // tratar a excepção!!!! System.Console.WriteLine("EXCEPÇÃO no componente 'UtilDB': " + ex); } finally { // fechar a conexão if (conn != null && conn.State != ConnectionState.Closed) conn.Close(); } // retornar valo return ret; } 4 static public DataSet FindByStringField(OleDbConnection conn, string table, string field, string key) { DataSet ret = new DataSet(); try { // criar um Datadapter para executar o comando e devolver o ret OleDbDataAdapter da = new OleDbDataAdapter( "SELECT * FROM " + table + " WHERE " + field + " LIKE ?", conn); da.SelectCommand.Parameters.AddWithValue("key", key + "%"); // executar o comando e preencher um Dataset da.Fill(ret, table); } catch (OleDbException ex) { // tratar a excepção!!!! System.Console.WriteLine( "EXCEPÇÃO no componente 'UtilDB': " + ex); } // retornar valor return ret; } 5 Interface associada à Pesquisa de Cliente por ID Pesquisar Cliente ClienteID Pesquisar O Cliente não existe Visible true or false 6 Página Pesquisa.aspx.cs public partial class PesquisarID : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Label2.Visible = false; DetailsView1.Visible = false; } } protected void Button1_Click(object sender, EventArgs e) { DetailsView1.Visible = false; Label2.Visible = false; long idCustomer = long.Parse(TextBox1.Text); ICustomer customer = Factory.CreateCustomerService(); DataSet ds = customer.GetByID("Joao", "Joao", idCustomer); try { if (ds.Tables[0].Rows.Count != 0) { DetailsView1.Visible = true; DetailsView1.DataSource = ds; DetailsView1.DataBind(); } else Label2.Visible = true; } catch (System.Exception) { Label2.Visible = true; } } } 7 Implementar na classe Customer o método public long Add(string user, string pass, string name, string address, string phone, string fax, string email, out ShopStatusEnum status) { long customerID = -1; OleDbConnection conn = null; // validar dados de entrada if (name == null || name.Trim().Length == 0) { status = ShopStatusEnum.InvalidArgument; return -1; } try { // criar objecto de conexão à base de dados e abrir a conexão conn = new OleDbConnection(UtilDB.CONN); conn.Open(); // validar o utilizador status = UtilDB.ValidateUser(conn, null, user, pass); if (status != ShopStatusEnum.OK) return -1; 8 // criar comando SQL a executar string sqlCmd = "INSERT INTO Customers (Name, Address, PhoneNb, FaxNb, EMail) Values (?, ?, ?, ?, ?)"; OleDbCommand cmd = new OleDbCommand(sqlCmd, conn); cmd.Parameters.AddWithValue("name", name); if (address == null || address.Length == 0) cmd.Parameters.AddWithValue("address", DBNull.Value); else cmd.Parameters.AddWithValue("address", address); if (phone == null || phone.Length == 0) cmd.Parameters.AddWithValue("phone", DBNull.Value); else cmd.Parameters.AddWithValue("phone", phone); if (fax == null || fax.Length == 0) cmd.Parameters.AddWithValue("fax", DBNull.Value); else cmd.Parameters.AddWithValue("fax", fax); if (email == null || email.Length == 0) cmd.Parameters.AddWithValue("email", DBNull.Value); else cmd.Parameters.AddWithValue("email", email); // executar o comando // int insRows = cmd.ExecuteNonQuery( ); 9 // verificar o resultado if (insRows == 0) // não inseriu registo status = ShopStatusEnum.NOT_OK; else { // inseriu registo // obter novo código de id gerado pela BD OleDbCommand idCmd = new OleDbCommand( "SELECT @@IDENTITY", conn); customerID = (int)idCmd.ExecuteScalar(); status = ShopStatusEnum.Ok; } } catch (OleDbException ex) { // tratar a excepção!!!! status = ShopStatusEnum.ERROR; } finally { // fechar a conexão if (conn != null && conn.State == ConnectionState.Open) conn.Close( ); } return customerID; } 10 Implementar na classe Customer o método public DataSet getAll(string user, string pass) { OleDbConnection conn; ShopStatusEnum status; try { // criar objecto de conexão à base de dados e abrir a conexão conn = new OleDbConnection(UtilDB.CONN); conn.Open(); // validar o utilizador status = UtilDB.ValidateUser(conn, null, user, pass); if (status != ShopStatusEnum.OK) return null; DataSet ds = UtilDB.getAllFromTable(conn, "Customers"); return ds; } catch (System.Exception) { return null; } } 11 Interface associada à Inserção de Cliente Inserir Cliente Name Address Phone Fax Email Inserir Registo inserido / não inserido 12 protected void ButtonInserir_Click(object sender, EventArgs e) { try { ShopStatusEnum st; string user = "Joao"; string pass = "Joao"; string name = TextBox1.Text; string address = TextBox2.Text; string phone = TextBox3.Text; string fax = TextBox4.Text; string email = TextBox5.Text; ICustomer customer = Factory.CreateCustomerService(); long id = customer.Add(user, pass, name, address, phone, fax, email, out st); if (id == -1) { Label6.Text = "Registo Não Inserido"; Label6.Visible = true; } else { Label6.Text = "Registo Inserido. ID=“+id.ToString(); Label6.Visible = true; TextBox1.Text = ""; TextBox2.Text = ""; TextBox3.Text = ""; Textox4.Text = ""; Textox5.Text = ""; } } catch (SystemException) { } } 13 Interface associada a Encomenda de Cliente Venda Cliente Produto Quantidade Add Produtos Comprados Fechar Facturta 14 Carregar as DropDownLists ICustomer clientes = Factory.CreateCustomerService(); DataSet dsClientes = clientes.getAll("Joao", "Joao"); if (dsClientes != null) { DropDownList1.DataTextField = "Name"; DropDownList1.DataValueField = "CustomerID"; DropDownList1.DataSource = dsClientes; DropDownList1.DataBind(); } IProduct produtos = Factory.CreateProductService(); DataSet dsProdutos = produtos.GetAll("Joao", "Joao"); if (dsProdutos != null) { DropDownList2.DataTextField = "Description"; DropDownList2.DataValueField = "ProductID"; DropDownList2.DataSource = dsProdutos; DropDownList2.DataBind(); } 15 Criar DataSet Vazio a partir da tabela SaleDetails ISale2 sale = Factory.CreateSale2Service(); DataSet dsDetalhes = sale.CreateDetails("Joao", "Joao"); //adicionar ao DataSet nova coluna Produto dsDetalhes.Tables[0].Columns.Add( "Produto"); //guardar o DataSet numa variável de Session Session["Detalhes"] = dsDetalhes; 16 Implementar na classe Sales o método public DataSet CreateDetails(string User, string Pass) { OleDbConnection conn = null; DataSet ds; try { // criar objecto de conexão à BD e abrir a conexão conn = new OleDbConnection(UtilDB.CONN); conn.Open(); // validar o utilizador if (UtilDB.ValidateUser(conn, null, User, Pass) !=ShopStatusEnum.OK) return null; // criar o dataset ds = UtilDB.GetById(conn, null, "SaleDetails", "SaleID", -1); if (ds == null) return null; // configurar as colunas para utilização ds.Tables["SaleDetails"].Columns["SaleID"].AllowDBNull = true; } catch (OleDbException ex) { // tratar a excepção!!!! return null; } finally { // fechar a conexão if (conn.State == ConnectionState.Open) conn.Close(); } return ds; } 17 Página Sales.aspx.cs public partial class Sales : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { ICustomer clientes = Factory.CreateCustomerService(); DataSet dsClientes = clientes.getAll("Joao", "Joao"); if (dsClientes != null) { DropDownList1.DataTextField = "Name"; DropDownList1.DataValueField = "CustomerID"; DropDownList1.DataSource = dsClientes; DropDownList1.DataBind(); } IProduct produtos = Factory.CreateProductService(); DataSet dsProdutos = produtos.GetAll("Joao", "Joao"); if (dsProdutos != null) { DropDownList2.DataTextField = "Description"; DropDownList2.DataValueField = "ProductID"; DropDownList2.DataSource = dsProdutos; DropDownList2.DataBind(); } GridView1.Visible = false; ISale2 sale = Factory.CreateSale2Service(); DataSet dsDetalhes = sale.CreateDetails("Joao", "Joao"); dsDetalhes.Tables[0].Columns.Add("Produto"); Session["Detalhes"] = dsDetalhes; } } 18 GridView RowCreated Event O evento RowCreated é accionado quando cada linha da Gridview é criada. Para esconder colunas da GridView Aceder a uma célula específica da linha e.Row.Cells[0].Visible = false; EXEMPLO protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e) { e.Row.Cells[0].Visible = false; e.Row.Cells[1].Visible = false; e.Row.Cells[3].Visible = false; } 19 Acrescentar linhas de encomenda Obter dados do Cliente Obter dados do produto Obter quantidade Aceder ao DataSet Detalhes guardado em Session para actualizar Criar nova linha Preencher campos Adicionar linha ao data set Guardar o novo DataSet Detalhes em Session Visualizar o dataSet na Gridview 20 Evento associado a Adicionar linha encomenda protected void Button1_Click(object sender, EventArgs e { // Obter dados string clienteID = DropDownList1.SelectedValue; string produtoID = DropDownList2.SelectedValue; string produtoname = DropDownList2.SelectedItem.Text; int qtd = int.Parse(TextBox1.Text); // Obter DataSet de variável de Session DataSet dsDetalhes = (DataSet)Session["Detalhes"]; // Criar linha na tabela 0 do data Set DataRow dr = dsDetalhes.Tables[0].NewRow(); // Preencher campos da linha dr["ProductID"] = produtoID; dr["Quantity"] = qtd; dr["Produto"] = produtoname; // Acrescentar linha à Tabela dsDetalhes.Tables["SaleDetails"].Rows.Add(dr); // Actualizar GridView GridView1.DataSource = dsDetalhes; GridView1.DataBind(); GridView1.Visible = true; // Guardar DataSet em variável de Session Session["Detalhes"] = dsDetalhes; } 21 Evento associado a Fechar Encomenda protected void Button2_Click(object sender, EventArgs e) { DataSet dsDetalhes = (DataSet)Session["Detalhes"]; ISale2 sale = Factory.CreateSale2Service(); sale.Add("Joao", "Joao", 22, DateTime.Now, dsDetalhes); GridView1.Visible = false; Button2.Visible = false; } 22 Método Add da classe Sales.cs public ShopStatusEnum Add(string User, string Pass, int CustomerID, DateTime Date, DataSet RsDetails) { //Abrir conexão com a BD conn = new OleDbConnection(UtilDB.CONN); conn.Open(); //Iniciar Transacção tx = conn.BeginTransaction(); //Validar User Pass if (UtilDB.ValidateUser(conn, tx, User, Pas s) != ShopStatusEnum.Ok) return ShopStatusEnum.InvalidLogOn; //Validar Cliente DataSet dsCust = UtilDB.GetById(conn, tx, "Customers", "CustomerID", CustomerID); if (dsCust.Tables["Customers"].Rows.Count == 0) return ShopStatusEnum.InvalidCustomerId; … 23 Validar Produtos e Quantidade… if (RsDetails.Tables["SaleDetails"].Rows.Count == 0) return ShopStatusEnum.InvalidArgument; int[ ] listaProd = new int[RsDetails.Tables["SaleDetails"].Rows.Count]; int i = 0; foreach (DataRow regDetails in RsDetails.Tables["SaleDetails"].Rows) { if (regDetails.IsNull("ProductID")) return ShopStatusEnum.InvalidArgument; if (regDetails.IsNull("Quantity")) return ShopStatusEnum.InvalidArgument; // verificar se este produto tem quantidade suficiente em stock e se existe! Product p = new Product(); ret = p.InStock(conn, tx, (int)regDetails["ProductID"], (int)regDetails["Quantity"]); if (ret != ShopStatusEnum.Ok) return ret; //guardar o código de produto para pesquisar listaProd[i++] = (int)regDetails["ProductID"]; } 24 RsDetails DataSet Detalhes da Encomenda //Criar um DataSet de produtos e preencher apenas com os produtos desejados DataSet pDS = UtilDB.GetById(conn, tx, "Products", "ProductID", listaProd) if (pDS == null) return ShopStatusEnum.InvalidProductId; //Calcular custo por linha foreach (DataRow regDetails in RsDetails.Tables["SaleDetails"].Rows) { // procurar o produto desejado DataRow[ ] row = pDS.Tables["Products"].Select("ProductId=" + regDetails["ProductID"].ToString()); // calcular custo desta linha da venda regDetails["TotalCost"] = (int)regDetails["Quantity"] * (float)row[0]["UnitPrice"]; } 25 Inserir Venda // criar comando para inserção OleDbCommand cmd = new OleDbCommand("INSERT INTO sales (customerid, dateofsale) VALUES (?, ?)", conn); cmd.Transaction = tx; cmd.Parameters.AddWithValue("custid", CustomerID); OleDbParameter parm = cmd.Parameters.Add("dt", OleDbType.Date); parm.Value = Date; // inserir registo cmd.ExecuteNonQuery(); // obter id autogerado OleDbCommand cmd2 = new OleDbCommand("SELECT @@IDENTITY", conn); cmd2.Transaction = tx; int id = (int)cmd2.ExecuteScalar(); 26 // inserir chave estrangeira nas linhas de detalhe foreach (DataRow regDetails in RsDetails.Tables["SaleDetails"].Rows) { regDetails["SaleID"] = id; } // inserir linhas de detalhe OleDbDataAdapter da = new OleDbDataAdapter( "SELECT * FROM SaleDetails", conn); da.SelectCommand.Transaction = tx; OleDbCommandBuilder cb = new OleDbCommandBuilder(da); da.Update(RsDetails, "SaleDetails"); // 27 RsDetails DataSet Detalhes da Encomenda //actualizar quantidades de produto em stock OleDbCommand cmd3 = new OleDbCommand( "UPDATE Products SET StockQtd=StockQtd-? WHERE ProductId=?", conn); cmd3.Transaction = tx; OleDbParameter p1 = cmd3.Parameters.Add("qtd", OleDbType.Integer); OleDbParameter p2 = cmd3.Parameters.Add("pid", OleDbType.Integer); foreach (DataRow regDetails in RsDetails.Tables["SaleDetails"].Rows) { p1.Value = regDetails["Quantity"]; p2.Value = regDetails["ProductID"]; cmd3.ExecuteNonQuery(); } // fechar transacção tx.Commit(); 28 verifica se existe uma determinada quantidade de um produto em armazem. internal ShopStatusEnum InStock (OleDbConnection conn, OleDbTransaction tx, int ProductID, int Quant) { DataSet rs = UtilDB.GetById(conn, tx, "Products", "ProductID", ProductID); if (rs == null) return ShopStatusEnum.NotOk; // validar stock if (rs.Tables["products"].Rows.Count > 0) return ((int)(rs.Tables["Products"].Rows[0]["StockQtd"]) >= Quant ? ShopStatusEnum.Ok :ShopStatusEnum.InsufficientStock); else return ShopStatusEnum.InvalidProductId; } 29 Em UtilDB GetByID static public DataSet GetById(OleDbConnection conn, OleDbTransaction tx, string table, string keyName, int[] keys) { DataSet ds = null; try { // criar objecto DataSet ds = new DataSet(); // criar um Datadapter para executar o comando e devolver o datase System.Text.StringBuilder sb = new System.Text.StringBuilder("Select * From " + table + " Where " + keyName + " IN ("); foreach (int k in keys) { sb.Append(k.ToString()); sb.Append(","); } sb.Length = sb.Length - 1; sb.Append(")"); string sSqlCmd = sb.ToString(); OleDbDataAdapter oAdapter = new OleDbDataAdapter(sSqlCmd, conn); oAdapter.SelectCommand.Transaction = tx; // executar o comando e preencher um Dataset oAdapter.Fill(ds, table); } catch (OleDbException ex) { // tratar a excepção!!!! System.Console.WriteLine("EXCEPÇÃO no método 'UtilDB.GetByID': " + ex.Message); ds = null; } return ds; } 30