Introducing Web Applications


Published on

1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Introducing Web Applications

  1. 1. CIS 407A Web Application Development Assistant Professor Kyvernitis Module 3: ADO .NET (viewing data from DB)
  2. 2. Outline <ul><li>Web Application Architecture: How do we create a stateful database applications on top of stateless HTTP? </li></ul><ul><li>How Visual Studio makes it easy for programmers – reduces the complexity introduced by html and http. Programmers can pretend they are writing a client server application. </li></ul><ul><li>Review DB terminology, review SQL select statements </li></ul><ul><li>ADO .NET Data Providers, ADO classes </li></ul>
  3. 3. Outline (Continued) <ul><li>Read data from a database, display in label of webform. </li></ul><ul><li>Use Parameterized SQL select statement (prevent SQL injection attack). </li></ul><ul><li>Use Like in SQL select statement (gives nice functionality). </li></ul><ul><li>Move data read code to a Class. </li></ul><ul><li>Use String Builder instead of string – more efficient for appending. </li></ul><ul><li>Build a html table to display data (not just text with newlines). </li></ul><ul><li>Format date and currency data for display. </li></ul><ul><li>Create reusable methods to prevent null value exceptions </li></ul>
  4. 4. Business Applications: <ul><li>Read from a database </li></ul><ul><li>Summarize and present information extracted from a database </li></ul><ul><li>Write (inserts, updates) to a database. </li></ul><ul><li>Access restricted based on secure logon and user role. </li></ul>
  5. 5. <ul><li>What is challenging about trying to put business applications on the web? </li></ul>
  6. 6. Web Architecture <ul><li>HTTP is the protocol used by web browsers and web servers. It is a “stateless” (“connectionless”) protocol in which: </li></ul><ul><ul><li>the client (browser) asks for a page, </li></ul></ul><ul><ul><li>that request is directed to the right server (by domain name), and </li></ul></ul><ul><ul><li>that server gives the requested (HTML) page back to the client. </li></ul></ul><ul><li>HTML is pretty limited (layout, pictures, links, javascript that can give a message box & move things around on the page, user input can be posted back to a web server). </li></ul><ul><li>The client PC/browser cannot communicate directly with any database. Why??? </li></ul>
  7. 7. Why Client PCs Don’t Talk to Databases <ul><li>HTTP (the protocol that governs the communication between client PC and web server) is connectionless- it gets a request from anyone, responds to that request and that’s it ! </li></ul><ul><ul><li>However, methods have been devised that enable web servers to keep session information about it’s users – remember login information per user, what they’ve done, and what they are trying to do. </li></ul></ul><ul><li>HTML (the language of web pages) has no commands for accessing a database. </li></ul><ul><ul><li>Those commands don’t exist because the purpose of HTML was to display information and links, not run database applications. </li></ul></ul><ul><ul><li>No one has added this functionality to HTML because companies don’t want their database server to be visible and accessible to all the PCs (and hackers) on the internet </li></ul></ul>
  8. 8. <ul><li>So, how did they put business applications on the internet?? </li></ul>
  9. 9. Web Application System Architecture
  10. 10. Web Application System Architecture <ul><li>The rightmost server is the database server (e.g., oracle or sql server database stored on it, dbms installed on it). This is the only place where database queries (select statements) and updates are run. The sql that is run may be saved in stored procedures (in the database) or it may be dynamically created by the web application (and presented to the dbms to be run). </li></ul><ul><li>The server in the lower left represents 1 or more application servers that typically all access the same database server. Your application logic (Business logic and presentation logic) runs here. We always try to separate business logic (what it is, how we can manipulate it) from presentation logic (how we want it to look). </li></ul><ul><li>The database server and the application servers are located “inside the firewall” of a company. </li></ul>
  11. 11. Web Application System Architecture <ul><li>Between the company’s application servers and the client’s PCs running browsers, there is the internet. </li></ul><ul><li>The application server can only hand the client PCs simple HTML possibly with some javascript in it. </li></ul>
  12. 12. .NET converts our webforms into plain HTML for us ! <ul><li>So, our middle tier code (business logic): </li></ul><ul><ul><li>accesses the database “in between” the generation of html pages (remember that a button click event causes the page to be regenerated, just like a new page request causes a page to be generated) </li></ul></ul><ul><ul><li>The database information can be incorporated into the generated page, e.g., a list of products pulled from the database, in response to user entered data. </li></ul></ul><ul><li>In addition to this, .NET: </li></ul><ul><ul><li>stores the state of the client (what they entered previously) in server side session variables. </li></ul></ul>
  13. 13. Web Applications <ul><li>If something changes on the client’s page (e.g., after a user clicked on button), this change was either caused by: </li></ul><ul><ul><li>javascript executing (e.g., an alert messagebox or javascript is writing to the document and changing the way the document looks). </li></ul></ul><ul><ul><li>or it is a new page (that looks a lot like the old page).  This is what is happening with the basic .NET code we are writing… </li></ul></ul>
  14. 14. Web Controls <ul><li>Examples: buttons, textboxes, radio buttons. </li></ul><ul><li>In design mode (to programmers) they look/act like windows application forms – except you avoid using events other than button click & perhaps dropdown list selections. </li></ul><ul><li>Also called ASP .NET server controls because they actually reside on the server (even tho they look like the reside in the client’s browser). And they only run on the server “in between” pages. </li></ul>
  15. 15. Database Terms (review) <ul><li>Database (most of today’s databases are relational databases): Microsoft SQL Server, Oracle, Sybase, DB2, Informix, MySQL, Microsoft Access. </li></ul><ul><li>DBMS – software that provides the only interface to read from or write to the database. This SW can enforce integrity rules, database constraints. </li></ul><ul><li>SQL (Structured Query Language)- the language we use (either thru SQL GUI interface or via programmatic control) to communicate with the DBMS – telling it what we want to read or write. </li></ul>
  16. 16. More Database Terms (review) <ul><li>Table – data that represents a set of objects, such as a group of employees, payments, departments. </li></ul><ul><li>Row = Record, e.g. a specific employee or payment or department (stored in a table). </li></ul><ul><li>Column = Field, e.g., employee’s name. Columns define a table’s layout. </li></ul><ul><li>Primary key – a field or fields that uniquely identify a row in a table, e.g., SS number, Department Code. </li></ul><ul><li>Foreign key – a field or fields that show a relationship from one record to another. For example, Employee.Dept_Code is a foreign key in the Employee table. It shows the Department where a particular Employee works. </li></ul>
  17. 17. Basic SQL Select Statements <ul><li>Select * from Titles; </li></ul><ul><li>Select Title, ISBN from Titles; </li></ul><ul><li>Select * from Titles where ISBN = ‘12345’; </li></ul><ul><li>Select * from Titles where Title like ‘Cat%’ order by Title ASC; </li></ul><ul><li>Select * from Titles, AuthorISBN, Author where Title.ISBN = AuthorISBN.ISBN and AuthorISBN.authorID = Authors.AuthorID and Author.lastName = ‘Poe’; (this called “inner join”) </li></ul>
  18. 18. ADO .NET <ul><li>ADO.NET stands for ActiveX Data Objects. It consists of two primary parts: </li></ul><ul><li>Data provider -- classes that provide access to a data source. Each type of database (e.g., sql server, oracle) has its own set of providers, but they all provide similar functionality including: </li></ul><ul><ul><li>Connection object: connection to the database. </li></ul></ul><ul><ul><li>Command object: such as select, insert, update, delete. </li></ul></ul><ul><ul><li>DataReader object: holds result sets from select statements. </li></ul></ul><ul><ul><li>DataAdapter object: A bridge used to transfer data between a data source and a DataSet object (see below). </li></ul></ul><ul><li>DataSet – classes that represent a simple in-memory relational database (e.g., tables, relationships, constraints). </li></ul>
  19. 19. ADO .NET Data Providers
  20. 20. ADO .NET Data Providers <ul><li>A data provider is a set of ADO .NET classes that let you access (read from, write to) a specific database. ADO .NET version 1.1 comes with these providers : </li></ul><ul><ul><li>ODBC (Open DataBase Connectivity): accesses any data source using db specific ODBC driver. </li></ul></ul><ul><ul><li>OLE DB ( Object Linking & Embedding-DataBase ): accesses any data source w/OLE DB driver, includes SQL Server earlier than v 7.0. This access method is a little more efficient than ODBC. </li></ul></ul><ul><ul><li>SQL Server: accesses SQL Svr DBs v 7.0 or later. This is the most efficient for SQL server databases. </li></ul></ul><ul><ul><li>Oracle: accesses Oracle DB (v 8i or later). This is the most efficient for oracle databases. </li></ul></ul>
  21. 21. Selecting a Data Provider <ul><li>1 st choice is a data provider that is optimized for your database. So, if SQL server 7.0 or later, use SQL server. If Oracle 8i or later, use Oracle. </li></ul><ul><li>Else, you’ll have to use OLE DB or ODBC. </li></ul><ul><li>For simplicity, we’ll use OLE DB with an MSAccess database in this class. </li></ul>
  22. 22. ADO .NET Ole Db Data Provider Classes <ul><li>OleDbConnection – manages a connection to a datasource (a particular database). </li></ul><ul><li>OleDbCommand – a specific SQL command to be executed. </li></ul><ul><li>OleDbDataReader – provides fast, read-only, forward-only access to query. </li></ul><ul><li>OleDbDataAdapter – connects to a datasource, runs an SQL command, and populates a DataSet (which can be modified then updated back to DB). </li></ul>
  23. 23. Add Using Statement to WebForm <ul><li>Add this at the top of WebForm1.aspx.cs </li></ul><ul><ul><li>using System.Data.OleDb; </li></ul></ul><ul><li>The “using” statement is like the java import statement. It enables you to have code like this: </li></ul><ul><li>OleDbDataReader reader; </li></ul><ul><li>Instead of having to use code like this: </li></ul><ul><li>System.Data.OleDb. OleDbDataReader reader; </li></ul><ul><li>Type in the code from the next slide into the button click event – or you can copy this code from the zipped project you just downloaded/extracted. </li></ul>
  24. 24. Code to Read From Database (without using Classes) <ul><li>private void btnGetData_Click(object sender, System.EventArgs e) { </li></ul><ul><li>this.lblDisplayData.Text = &quot;&quot;; // clear value if there is any </li></ul><ul><li>string strCon = &quot;Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:ayroll.mdb&quot;; </li></ul><ul><li>OleDbConnection con = new OleDbConnection(strCon); </li></ul><ul><li>OleDbDataReader reader; </li></ul><ul><li>try { </li></ul><ul><li>string sql = &quot;SELECT FirstName, LastName FROM emp&quot;; </li></ul><ul><li>OleDbCommand cmd = new OleDbCommand(sql,con); </li></ul><ul><li>con.Open(); </li></ul><ul><li>reader = cmd.ExecuteReader(); </li></ul><ul><li>while (reader.Read()) { </li></ul><ul><li>this.lblDisplayData.Text += reader.GetValue(0).ToString() + &quot; &quot;; </li></ul><ul><li>this.lblDisplayData.Text += reader.GetValue(1).ToString() + &quot;<br>&quot;; </li></ul><ul><li>} </li></ul><ul><li>reader.Close(); </li></ul><ul><li>con.Close(); </li></ul><ul><li>} // continued on next slide </li></ul>
  25. 25. Code to Read From Database (without using Classes -- continued) <ul><li>// .. Continued from previous slide </li></ul><ul><li>catch (Exception ex) { </li></ul><ul><li>this.lblDisplayData.Text=ex.Message; </li></ul><ul><li>con.Close(); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  26. 26. Using ADO
  27. 27. The GetValue input parameter is based on the order of cols in the SQL select statement (not the order of cols as designed in the DB table). <ul><li>// … </li></ul><ul><li>string sql = &quot;SELECT FirstName, LastName FROM emp&quot;; </li></ul><ul><li>//… </li></ul><ul><li>while (reader.Read()) { </li></ul><ul><li>this.lblDisplayData.Text += reader.GetValue(0).ToString() + &quot; &quot;; </li></ul><ul><li>this.lblDisplayData.Text += reader.GetValue(1).ToString() + “<br>&quot;; </li></ul><ul><li>} </li></ul><ul><li>GetValue(0) gets the first column as specified in the SQL statement. </li></ul><ul><li>GetValue(1) gets the next column as specified in the SQL statement. </li></ul><ul><li>GetValue(2) would get the next column after that, and so on. </li></ul><ul><li>The GetValue parameter has nothing to do with the order of the columns when looking at the table in design mode in MSAccess. </li></ul><ul><li>Use GetValue instead of GetString or GetInt so we don’t abort on say a null value in the database. </li></ul>
  28. 28. How to Deal with Runtime errors caused by bad SQL <ul><li>If there is a syntax error in your SQL statement, your program will abort at runtime. Unfortunately, you will not get a compiler error. </li></ul><ul><li>All database access should be put in a try block. Of course, the try block should close the connection when the connection is no longer needed. The catch block should also close the connection – or else you’ll get a “file in use” error the next time you try to run after you’ve encountered an error. </li></ul><ul><li>At any rate, if you ever run into a message like “file already in use” – you may have to close Visual Studio, reopen and retry. If this doesn’t fix it, you can try rebooting. </li></ul><ul><li>Make sure that you ALWAYS close every connection you open (for every code path, including error code paths). </li></ul>
  29. 29. Handling Errors <ul><li>There are two common errors: </li></ul><ul><ul><li>The database is not available. </li></ul></ul><ul><ul><li>There is a error in the SQL (maybe syntax or maybe a table or field misspelled). </li></ul></ul><ul><li>We can easily simulate both errors: </li></ul><ul><ul><li>Misspell database name (acts like db not available). </li></ul></ul><ul><ul><li>Misspell a SQL keyword (SQL syntax error). </li></ul></ul><ul><li>Make sure your program is resilient to both potential problems. You want your code to close any open connection to the database (even if there IS an error) or you’ll have trouble running/testing your program next time. Do this by closing the connection in the try code as well as in the catch code. Otherwise, you’ll have to restart VS and/or reboot everytime you test and this is a frustrating way to code. </li></ul>
  30. 30. Invasive SQL Injection Attacks <ul><li>Suppose you have a webform where the user enters in a customer name into a textbox and then presses a button to see that customer’s record. </li></ul><ul><li>If the program incorporates the user’s data directly into the sql select statement (without using a parameterized sql statement), we open ourselves up to a SQL injection attack. </li></ul><ul><li>Here is an example of a sql statement that is open to SQL injection attack: </li></ul><ul><li>string sql = “select * from Cust where name = ‘ ” + txtName.Text + “ ’ ”; </li></ul><ul><li>So, if the user enters “Smith” into the textbox, then the expression above evaluates to this: </li></ul><ul><li>select * from Cust where name = ‘Smith’ </li></ul>
  31. 31. Invasive SQL Injection Attacks … <ul><li>string sql = “select * from Cust where name = ‘ ” + txtName.Text + “ ’ ”; </li></ul><ul><li>A malicious (technically savvy) user could enter this into the textbox: </li></ul><ul><ul><li>Smith’ or ‘1’=‘1 </li></ul></ul><ul><li>Then the expression evaluates to: </li></ul><ul><li>select * from Cust where name = ‘ Smith’ or ‘1’=‘1 ’ </li></ul><ul><li>Then the user would see all of the (possibly sensitive) data in the customer file. </li></ul>
  32. 32. Destructive Sql Injection Attacks <ul><li>Or (assuming same web form) the user enters this into the textbox: </li></ul><ul><ul><ul><li>Smith’ ; delete * from Cust - - </li></ul></ul></ul><ul><li>The expression then evaluates to this (much more malicious than the previous example): </li></ul><ul><ul><ul><li>select * from Cust where name = ‘ Smith’; </li></ul></ul></ul><ul><ul><ul><li>delete * from Cust-- ’ </li></ul></ul></ul><ul><ul><li>; ends the first sql statement and lets you start another statement. </li></ul></ul><ul><ul><li>- - comments out the rest of the statement </li></ul></ul>
  33. 33. Parameterized SQL Commands <ul><li>Parameterized SQL commands prevent SQL injection attacks. </li></ul><ul><li>Parameterized SQL commands automatically create stored procedures within the database (assuming the db provides stored procedures – MSAccess does not). </li></ul><ul><li>When the DBMS (Database Mgt System, e.g. oracle or Sql) sees a new parameterized SQL command, it compiles it, uses it, and saves it for the next time. </li></ul><ul><li>Stored also procedures run much more quickly than plain text sql statements because they are pre-compiled (by the DBMS). </li></ul>
  34. 34. Example of Parameterized SQL Command (not open to Sql Injection Attack) <ul><li>string sql = &quot;SELECT FirstName, LastName FROM emp &quot; </li></ul><ul><li>+ &quot;where LastName = @lname&quot;; </li></ul><ul><li>OleDbCommand cmd = new OleDbCommand(sql,con); </li></ul><ul><li>cmd.Parameters.Add(&quot;@lname&quot;,&quot;Willis&quot;); </li></ul><ul><li>con.Open(); </li></ul><ul><li>System.Data.OleDb.OleDbDataReader reader; </li></ul><ul><li>reader = cmd.ExecuteReader(); </li></ul><ul><li>… </li></ul><ul><li>// In this example, you’ll see all the first and last name of all emp records where the last name = ‘Willis’ </li></ul>
  35. 35. Tip on Using Parameterized SQL <ul><li>Always replace parameters in the same order they occur in the SQL statement. For example, call the Add method for @lname THEN call the Add method for @fname. </li></ul><ul><li>string sql = &quot;SELECT FirstName, LastName FROM emp &quot; </li></ul><ul><li>+ &quot;where LastName = @lname or FirstName = @fname&quot;; </li></ul><ul><li>OleDbCommand cmd = new OleDbCommand(sql,con); </li></ul><ul><li>cmd.Parameters.Add(&quot;@lname&quot;,&quot;Willis&quot;); </li></ul><ul><li>cmd.Parameters.Add(&quot;@lname&quot;,“Bruce&quot;); </li></ul>
  36. 36. Using LIKE in SQL Select Statement <ul><li>string sql = &quot;SELECT FirstName, LastName FROM emp &quot; </li></ul><ul><li>+ &quot;where LastName like @lname&quot;; </li></ul><ul><li>OleDbCommand cmd = new OleDbCommand(sql,con); </li></ul><ul><li>cmd.Parameters.Add(&quot;@lname&quot;,&quot;Will % &quot;); </li></ul><ul><li>con.Open(); </li></ul><ul><li>System.Data.OleDb.OleDbDataReader reader; </li></ul><ul><li>reader = cmd.ExecuteReader(); </li></ul><ul><li>… </li></ul><ul><li>% is a wild card character </li></ul><ul><li>This gets all the records where last name Starts With ‘Will’ </li></ul>
  37. 37. Create Database Connection Wrapper Class <ul><li>You can design flexible data access software by “putting a wrapper around” the data provider classes (e.g., Connection, Command, Reader). </li></ul><ul><li>For example, when you first start designing a web application, you use a simple Access database (cheaper, easier to obtain) and plan to switch to a more robust database later. </li></ul><ul><li>So, rather that directly using OleDbConnection, etc, you can create your own Connection class that is just a “wrapper” around OleDbConnection. When you upgrade to different DB, just modify that Connection class (e.g., to be a SQL server Connection class). </li></ul>
  38. 38. A Closer Look at our Connection Wrapper Class DbConn – its data members <ul><li>using System.Data.OleDb; </li></ul><ul><li>public class DbConn { </li></ul><ul><li>// the actual connection </li></ul><ul><li>private OleDbConnection conn; </li></ul><ul><li>// error message if there was a problem </li></ul><ul><li>private string errMsg; </li></ul>
  39. 39. DbConn class (Constructor) <ul><li>// Constructor creates then opens a db connection. </li></ul><ul><li>public DbConn() { </li></ul><ul><li>try { </li></ul><ul><li>string myConnectionString = </li></ul><ul><li>&quot;Provider=Microsoft.Jet.OLEDB.4.0;Data &quot;+ </li></ul><ul><li>&quot;Source=C:ayroll.mdb&quot;; </li></ul><ul><li>conn = new OleDbConnection(myConnectionString); </li></ul><ul><li>conn.Open(); </li></ul><ul><li>} </li></ul><ul><li>catch (Exception ex) { </li></ul><ul><li>this.errMsg = &quot;Could not access database. Error: &quot; + </li></ul><ul><li>ex.Message + &quot; &quot;; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  40. 40. Create DbConn class (other methods) <ul><li>public OleDbConnection getConn(){ </li></ul><ul><li>return conn; </li></ul><ul><li>} </li></ul><ul><li>public void closeConn(){ </li></ul><ul><li>conn.Close(); </li></ul><ul><li>} </li></ul>
  41. 41. Create DbConn class (other methods) <ul><li>public bool isConnErr(){ </li></ul><ul><li>string state = conn.State.ToString(); </li></ul><ul><li>if (state.Equals(&quot;Open&quot;)) </li></ul><ul><li>return false; </li></ul><ul><li>else { </li></ul><ul><li> this.errMsg=“DB connection is not open.”; </li></ul><ul><li> return true; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>public string getErrMsg(){ </li></ul><ul><li>return this.errMsg; </li></ul><ul><li>} </li></ul>
  42. 42. DB Connection Management <ul><li>Waiting to get a db connection can be slow (one computer requests of another, over a network). </li></ul><ul><li>I timed it once (oracle) at about 2-3 seconds per connection. </li></ul><ul><li>If one page request (either new page or button click on same page) asks for 5 database connections, this can add 10-15 seconds onto the time that a user has to wait for the page. </li></ul>
  43. 43. DB Connection Management: Just get one per page – pass it around. <ul><li>One simple but effective way of managing database connections is to get one in the page (e.g., button click event, or page load event) and pass that single one around to whoever needs it. Then, make sure to close it (every code path). </li></ul><ul><li>Don’t get more than one database connection per page since this is an unnecessary waste. If a particular page is heavily hit, you’ll require twice or three times as many database connections. </li></ul><ul><li>The general limit of database connections (that I’ve seen in industry) is about 90 or so. It depends on various factors. </li></ul>
  44. 44. DB Connection Management: Close every connection that’s opened <ul><li>EVERY time a connection is opened it MUST be closed. </li></ul><ul><li>If there’s even one code path where a db connection is opened but not closed, this creates a db connection leak. If this code path is heavily used, then the database will run out of connections, the application will fail -- until the database server is rebooted. User work will be lost. </li></ul><ul><li>If this code path is not heavily used, then its possible that the database server will not need to be rebooted (each connection will “time out” if not used over a certain time period, as determined by the database administrator). </li></ul>
  45. 45. DB Connection Management – DB Connection Pooling <ul><li>To combat this potential area of slowness, database servers (e.g., oracle software) and application servers (e.g., .NET software) employ connection pooling. That is to say, they request connections ahead of time and have a limited number of them already available. </li></ul><ul><li>In order to take advantage of this connection pooling, however, you must specify the connection exactly the same way each time to try to access a particular database. This can best be accomplished by funneling all db connection requests through a single class – your database wrapper class. </li></ul>
  46. 46. Closer look at EmpRead class’s data members & constructor <ul><li> private DbConn dbc; // db connection </li></ul><ul><li>private string errMsg; // error msg </li></ul><ul><li>private bool err; // is there an error? </li></ul><ul><li>public EmpRead(DbConn dbc) { </li></ul><ul><li>this.dbc=dbc; </li></ul><ul><li>} </li></ul>
  47. 47. Put all SQL access into Same Class <ul><li>In our architecture, we create a SQL class that holds all the access to a particular table. </li></ul><ul><li>That way, if changes are made to the database, we know where we’ll have to change the code (in the SQL classes). </li></ul><ul><li>In our Sample code, we put the SQL into a class called StockRead. </li></ul>
  48. 48. Examine method (1/3) <ul><li>public string read(string lastNameLike) { </li></ul><ul><li>this.err=false; </li></ul><ul><li>this.errMsg=&quot;&quot;; </li></ul><ul><li>string tmp = &quot;&quot;; </li></ul><ul><li>OleDbConnection con = dbc.getConn(); </li></ul><ul><li>if (dbc.isConnErr()) { </li></ul><ul><li>this.err=true; </li></ul><ul><li>this.errMsg=dbc.getErrMsg(); </li></ul><ul><li>return &quot;*** Error Connecting to Database ***&quot;; </li></ul><ul><li>} </li></ul><ul><li>// continued on next slide </li></ul>
  49. 49. Examine method (2/3) <ul><li>// continued from … public string read(string lastNameLike) { </li></ul><ul><li>try { </li></ul><ul><li>string sql = &quot;SELECT FirstName, LastName FROM emp &quot;+ </li></ul><ul><li>&quot;where LastName LIKE @nameParm&quot;; </li></ul><ul><li>OleDbCommand cmd = new OleDbCommand(sql,con); </li></ul><ul><li>cmd.Parameters.Add(&quot;@nameParm&quot;,lastNameLike+&quot;%&quot;); </li></ul><ul><li>System.Data.OleDb.OleDbDataReader reader; </li></ul><ul><li>reader = cmd.ExecuteReader(); </li></ul><ul><li>while (reader.Read()) { </li></ul><ul><li>tmp += reader.GetValue(0).ToString() + &quot; &quot;; </li></ul><ul><li>tmp += reader.GetValue(1).ToString() + &quot;<br>&quot;; </li></ul><ul><li>} </li></ul><ul><li>reader.Close(); </li></ul><ul><li>} </li></ul>
  50. 50. Examine method (3/3) <ul><li>// continued from … public string read(string lastNameLike) { </li></ul><ul><li> catch (Exception e){ </li></ul><ul><li>this.err=true; </li></ul><ul><li>this.errMsg=e.Message; </li></ul><ul><li> } </li></ul><ul><li> return tmp; </li></ul><ul><li>} </li></ul>
  51. 51. Use StringBuilder instead of String (more efficient when appending) <ul><li>using System.Text; </li></ul><ul><li>… </li></ul><ul><li>StringBuilder s = new StringBuilder(); </li></ul><ul><li>while (reader.Read()) { </li></ul><ul><li>s.Append(reader.GetValue(0).ToString() + &quot; &quot;); </li></ul><ul><li>s.Append(reader.GetValue(1).ToString() + “<br>&quot;); </li></ul><ul><li>} </li></ul><ul><li>reader.Close(); </li></ul><ul><li>con.Close(); </li></ul><ul><li>return s.ToString(); </li></ul><ul><li>// MAKE THESE CHANGES to the read method of the EmpRead Class </li></ul>
  52. 52. Build a String that contains a html table full of data <ul><li>StringBuilder s = new StringBuilder(); </li></ul><ul><li>s.Append(“<table border = ‘1’> ”); </li></ul><ul><li>while (reader.Read()) { </li></ul><ul><li>s.Append(“ <tr> ”); </li></ul><ul><li>s.Append(“ <td>”+reader.GetValue(0).ToString() + “</td> &quot;); </li></ul><ul><li>s.Append(“ <td>”+reader.GetValue(1).ToString() + &quot;</td> &quot;); </li></ul><ul><li>s.Append(“ </tr> ”); </li></ul><ul><li>} </li></ul><ul><li>s.Append(“</table>”); </li></ul><ul><li>reader.Close(); </li></ul><ul><li>// Nicer layout for display on the form… </li></ul><ul><li>// Make changes in EmpRead read method </li></ul>
  53. 53. Formatting Currency and Date Values <ul><li>// Convert to string applying a currency format </li></ul><ul><li>s.Append(reader.GetDecimal(2).ToString(&quot;C&quot;) + &quot; &quot;); </li></ul><ul><li>// Convert to string applying a date format </li></ul><ul><li>s.Append(reader.GetDateTime(3).ToString(&quot;d&quot;) + &quot; &quot;); </li></ul><ul><li>How can you find this out again (in case you loose this info)? </li></ul><ul><li>Click on “ToString” Method anywhere in your code, press F1 (context sensative help). Click on IFormattable. Click on IFormatProvider. Click on DateTimeFormatInfo or NumberFormatInfo. Then scroll down to see a list of available formats (like the C and d shown above). </li></ul>
  54. 54. Reading Null DB Values will Create Exception <ul><li>Previous sample code aborts if it encounters a null value from the database. Create reusable utility methods to deal with this: </li></ul><ul><li>private string getDate(OleDbDataReader reader, int pos) { </li></ul><ul><ul><li>try { </li></ul></ul><ul><ul><li>return reader.GetDateTime(pos).ToString(&quot;d&quot;); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>catch (Exception e) { // exception thrown if reading null </li></ul></ul><ul><ul><li>return &quot;--/--/----&quot;; </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>