lecture 11: programmatic database access with ado.net

31
Lecture 11: Programmatic Database Access with ADO.NET

Upload: may-daniels

Post on 23-Dec-2015

228 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Lecture 11: Programmatic Database Access with ADO.NET

Lecture 11:

Programmatic Database Access with ADO.NET

Page 2: Lecture 11: Programmatic Database Access with ADO.NET

11-2MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Objectives

“Programmatic database access typically involves executing SQL queries using classes from the language's framework. In .NET, the Active Data Objects (ADO) classes in the FCL are the primary means of database programming. ADO.NET is a vendor-neutral, object-oriented, SQL-based approach…”

• Architecture of ADO.NET• Basic database access• Application design• Updating a database• DataSets

Page 3: Lecture 11: Programmatic Database Access with ADO.NET

11-3MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Part 1

• Architecture of ADO.NET…

Page 4: Lecture 11: Programmatic Database Access with ADO.NET

11-4MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Relational technology

• ADO.NET is designed to access relational databases• Example:

– Sales database with customers, orders, and products

Page 5: Lecture 11: Programmatic Database Access with ADO.NET

11-5MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Architecture

• ADO.NET architecture based on data providers

– data providers encapsulate DB-specific details

Data Provider

ADO.NET

.NET Programmer

DB

Page 6: Lecture 11: Programmatic Database Access with ADO.NET

11-6MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Existing data providers

• .NET currently ships with 4 data providers:– one for Microsoft SQL Server– one for Oracle– one for older OLEDB technology (used for ADO, VB6)– one for older ODBC (Open Database Connectivity) technology

• More third-party providers are available…– Oracle's own provider: http://otn.oracle.com/tech/windows/odpnet/

– DB2: http://www7b.software.ibm.com/dmdd/downloads/dotnetbeta/

– MySQL: http://www.mysql.com/, http://crlab.com/mysqlnet/

– etc.

Page 7: Lecture 11: Programmatic Database Access with ADO.NET

11-7MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

ADO.NET object model

• ADO.NET is an object-oriented approach• Classes are spread across a number of FCL namespaces

– some are provider-neutral, others are provider-specific

SQL Server

System.Data.Common

System.Data

System.Data.SqlClient

System.Data.OleDb

other DBs, e.g. MS Access

provider-neutral

ODBC (Open Database Connectivity)

System.Data.Odbc

Page 8: Lecture 11: Programmatic Database Access with ADO.NET

11-8MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Part 2

• Basic database access…

Page 9: Lecture 11: Programmatic Database Access with ADO.NET

11-9MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Overview of database access

• Three steps:

1. open connection to database

2. execute SQL to retrieve records / update DB

3. close connection

Page 10: Lecture 11: Programmatic Database Access with ADO.NET

11-10MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

import System.Data.*;import System.Data.OleDb.*;

String sConnection;sConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=Sales.mdb";

OleDbConnection dbConn;dbConn = new OleDbConnection(sConnection);dbConn.Open();

MessageBox.Show(dbConn.get_State().toString());

import System.Data.*;import System.Data.OleDb.*;

String sConnection;sConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=Sales.mdb";

OleDbConnection dbConn;dbConn = new OleDbConnection(sConnection);dbConn.Open();

MessageBox.Show(dbConn.get_State().toString());

(1) Open connection

• Connections are opened based on connection string info– here we open a connection to a MS Access 2000 database– "Sales.mdb" must exist in same dir as .EXE (e.g. bin\Debug)

connection

Page 11: Lecture 11: Programmatic Database Access with ADO.NET

11-11MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Building connection strings

• Connection strings are vendor-specific• Connection strings are not well-documented• Where to turn for help?

– www.connectionstrings.com– www.able-consulting.com/ADO_conn.htm

Page 12: Lecture 11: Programmatic Database Access with ADO.NET

11-12MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

(2) Retrieve records

• Retrieve records via SQL Select query– read-only access via DataReader & field names

String sql, fn, ln; Customer c;sql = "Select * From Customers Order By LastName Asc, FirstName Asc;";

OleDbCommand dbCmd;OleDbDataReader dbReader;

dbCmd = new OleDbCommand(sql, dbConn);dbReader = dbCmd.ExecuteReader();

while ( dbReader.Read() ) // retrieve records one-by-one… {

fn = String.valueOf(dbReader.get_Item("FirstName")); ln = String.valueOf(dbReader.get_Item("LastName")); c = new Customer(fn, ln); this.listBox1.get_Items().Add(c);

}

String sql, fn, ln; Customer c;sql = "Select * From Customers Order By LastName Asc, FirstName Asc;";

OleDbCommand dbCmd;OleDbDataReader dbReader;

dbCmd = new OleDbCommand(sql, dbConn);dbReader = dbCmd.ExecuteReader();

while ( dbReader.Read() ) // retrieve records one-by-one… {

fn = String.valueOf(dbReader.get_Item("FirstName")); ln = String.valueOf(dbReader.get_Item("LastName")); c = new Customer(fn, ln); this.listBox1.get_Items().Add(c);

}

data reader recordrecordrecord

field name of data value in current record

command connection

Page 13: Lecture 11: Programmatic Database Access with ADO.NET

11-13MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

(3) Close connection

• Be sure to close reader and connection…– to flush pending updates (in general)– so others can access DB (connections are limited resources)

dbReader.Close();dbConn.Close();dbReader.Close();dbConn.Close();

Page 14: Lecture 11: Programmatic Database Access with ADO.NET

11-14MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Part 3

• Data-driven application design…

Page 15: Lecture 11: Programmatic Database Access with ADO.NET

11-15MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Data Tier design

• Recall N-Tier design… GUI.exe DataAccess

import System.Data.*;import System.Data.OleDb.*;

public class DataAccess{ private String sConnection;

public DataAccess(String filename) { this.sConnection = String.Format("Provider=...;Data Source={0}{1}", System.AppDomain.get_CurrentDomain().get_BaseDirectory(), filename); }

public java.util.ArrayList getCustomers() throws System.Exception { . . . }

import System.Data.*;import System.Data.OleDb.*;

public class DataAccess{ private String sConnection;

public DataAccess(String filename) { this.sConnection = String.Format("Provider=...;Data Source={0}{1}", System.AppDomain.get_CurrentDomain().get_BaseDirectory(), filename); }

public java.util.ArrayList getCustomers() throws System.Exception { . . . }

Page 16: Lecture 11: Programmatic Database Access with ADO.NET

11-16MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Guaranteed close?

• Ensure reader / DB closed via try-catch-finally pattern– and *note* that we want to catch .NET System.Exception objects, not

Java java.lang.Exception objects…

OleDbConnection dbConn = null;OleDbDataReader dbReader = null;

try { dbConn = new OleDbConnection(…); dbConn.Open(); . . .}catch(System.Exception ex) { System.Diagnostics.Debug.WriteLine("DB error: " + ex.get_Message()); throw new System.Exception("Data Error!", ex);}finally { // always executes whether we succeed or throw exception… if (dbReader != null) dbReader.Close(); if (dbConn != null) dbConn.Close();}

OleDbConnection dbConn = null;OleDbDataReader dbReader = null;

try { dbConn = new OleDbConnection(…); dbConn.Open(); . . .}catch(System.Exception ex) { System.Diagnostics.Debug.WriteLine("DB error: " + ex.get_Message()); throw new System.Exception("Data Error!", ex);}finally { // always executes whether we succeed or throw exception… if (dbReader != null) dbReader.Close(); if (dbConn != null) dbConn.Close();}

Page 17: Lecture 11: Programmatic Database Access with ADO.NET

11-17MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Part 4

• Updating a database…

Page 18: Lecture 11: Programmatic Database Access with ADO.NET

11-18MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Executing action queries

• Use action queries when you need to modify a DB– updates– inserts– deletes

• Execute action queries via ExecuteNonQuery method…

Page 19: Lecture 11: Programmatic Database Access with ADO.NET

11-19MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Basic idea

• Open, execute, and close:

String sConnection, sql;sConnection = "...";sql = "...";

OleDbConnection dbConn; OleDbCommand dbCmd;dbConn = new OleDbConnection(sConnection);dbCmd = new OleDbCommand(sql, dbConn);

int rows;dbConn.Open(); rows = dbCmd.ExecuteNonQuery(); // returns # of rows affected…dbConn.Close();

if (rows != 1) // sanity check to make sure it worked... throw new System.Exception("Query ran but failed to update DB?!");

String sConnection, sql;sConnection = "...";sql = "...";

OleDbConnection dbConn; OleDbCommand dbCmd;dbConn = new OleDbConnection(sConnection);dbCmd = new OleDbCommand(sql, dbConn);

int rows;dbConn.Open(); rows = dbCmd.ExecuteNonQuery(); // returns # of rows affected…dbConn.Close();

if (rows != 1) // sanity check to make sure it worked... throw new System.Exception("Query ran but failed to update DB?!");

Page 20: Lecture 11: Programmatic Database Access with ADO.NET

11-20MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Dynamic SQL

• Most of the time you'll need to build SQL dynamically– i.e. based on input values from the user

• Example:– delete the selected customer…

String fn, ln; Customer c;

c = this.listBox1.get_SelectedItem();fn = c.firstName;ln = c.lastName;

sql = "...";

String fn, ln; Customer c;

c = this.listBox1.get_SelectedItem();fn = c.firstName;ln = c.lastName;

sql = "...";

Page 21: Lecture 11: Programmatic Database Access with ADO.NET

11-21MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Dynamic string building

• Dynamic SQL requires dynamic string building• Example:

– build dynamic SQL to delete selected customer…

– don't forget the delimiters for strings & dates!

String sql;

sql = String.Format("Delete From Customers Where " + "FirstName='{0}' And LastName='{1}';", fn, ln);

String sql;

sql = String.Format("Delete From Customers Where " + "FirstName='{0}' And LastName='{1}';", fn, ln);

Page 22: Lecture 11: Programmatic Database Access with ADO.NET

11-22MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Example

• Delete selected customer…

private void listBox1_SelectedIndexChanged(…){ String fn, ln, sql; int rows; Customer c; c = (Customer) this.listBox1.get_SelectedItem(); if (c == null) return; // nothing selected…

fn = c.firstName; ln = c.lastName; sql = String.Format("Delete From Customers Where " + "FirstName='{0}' And LastName='{1}';", fn, ln); . . . dbConn.Open(); rows = dbCmd.ExecuteNonQuery(); // delete! dbConn.Close();

if (rows != 1) throw new System.Exception("Query ran but failed to delete?!");

this.listBox1.get_Items().Remove(c); // update GUI! MessageBox.Show("Deleted!");}

private void listBox1_SelectedIndexChanged(…){ String fn, ln, sql; int rows; Customer c; c = (Customer) this.listBox1.get_SelectedItem(); if (c == null) return; // nothing selected…

fn = c.firstName; ln = c.lastName; sql = String.Format("Delete From Customers Where " + "FirstName='{0}' And LastName='{1}';", fn, ln); . . . dbConn.Open(); rows = dbCmd.ExecuteNonQuery(); // delete! dbConn.Close();

if (rows != 1) throw new System.Exception("Query ran but failed to delete?!");

this.listBox1.get_Items().Remove(c); // update GUI! MessageBox.Show("Deleted!");}

Page 23: Lecture 11: Programmatic Database Access with ADO.NET

11-23MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Oops!

• Try to delete "O'Dahl, Kathie"…• What happens?

Page 24: Lecture 11: Programmatic Database Access with ADO.NET

11-24MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Escaping delimiters

• Most common DB programming mistake:– forgetting to escape delimiter characters…

• Solution?– just replace ' with 2 in a row, i.e. ' '

private void listBox1_SelectedIndexChanged(…){ String fn, ln, sql; int rows; Customer c; c = (Customer) this.listBox1.get_SelectedItem(); if (c == null) return; // nothing selected…

fn = c.firstName; ln = c.lastName;

fn = fn.Replace("'", "''"); ln = ln.Replace("'", "''"); sql = String.Format("Delete From Customers Where " + "FirstName='{0}' And LastName='{1}';", fn, ln);

private void listBox1_SelectedIndexChanged(…){ String fn, ln, sql; int rows; Customer c; c = (Customer) this.listBox1.get_SelectedItem(); if (c == null) return; // nothing selected…

fn = c.firstName; ln = c.lastName;

fn = fn.Replace("'", "''"); ln = ln.Replace("'", "''"); sql = String.Format("Delete From Customers Where " + "FirstName='{0}' And LastName='{1}';", fn, ln);

Page 25: Lecture 11: Programmatic Database Access with ADO.NET

11-25MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Part 5

• DataSets…

Page 26: Lecture 11: Programmatic Database Access with ADO.NET

11-26MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

DataSets

• DataSets are an in-memory data structure– easily filled with data from a database– easily passed around– easily displayed in a GUI app

DataSet

Name Price Stock

Ants $ 0.49 5000

Birds $ 4.49 500

Cats $29.95 100

Dogs $79.95 20

DBCommand ConnectionDataAdapter

• DataSet mirrors the database– data forms a temporary table called

"Table" within DataSet"Table"

Page 27: Lecture 11: Programmatic Database Access with ADO.NET

11-27MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Filling a DataSet

• DataAdapter object is used to fill a DataSet…• Example:

– fill DataSet with all product data

sql = "Select * From Products Order By Name Asc;"; . . .DataSet ds;OleDbDataAdapter adapter;ds = new DataSet();adapter = new OleDbDataAdapter(dbCmd);

dbConn.Open(); adapter.Fill(ds);dbConn.Close();

sql = "Select * From Products Order By Name Asc;"; . . .DataSet ds;OleDbDataAdapter adapter;ds = new DataSet();adapter = new OleDbDataAdapter(dbCmd);

dbConn.Open(); adapter.Fill(ds);dbConn.Close();

"Table"

Name Price Stock

Ants $ 0.49 5000

Birds $ 4.49 500

Cats $29.95 100

Dogs $79.95 20

Page 28: Lecture 11: Programmatic Database Access with ADO.NET

11-28MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

DataGrid display

• DataSet can be bound to DataGrid control for easy display– one line of code!

. . .this.dataGrid1.SetDataBinding(ds, "Table");

. . .this.dataGrid1.SetDataBinding(ds, "Table");

Page 29: Lecture 11: Programmatic Database Access with ADO.NET

11-29MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

DataGrid is a powerful control

• By default, DataGrid is read/write– user can modify data– user can add rows– user can delete rows

• However, all changes are local to DataSet– to flush changes back to DB, reconnect and update…

Page 30: Lecture 11: Programmatic Database Access with ADO.NET

11-30MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Flushing changes back to database

• Reconnect, and apply adapter's Update() method– use CommandBuilder object to generate necessary SQL for you

// retrieve existing data set from grid…ds = (DataSet) this.dataGrid1.get_DataSource();

. . .

OleDbCommandBuilder cmdBuilder;cmdBuilder = new OleDbCommandBuilder(adapter);

dbConn.Open(); adapter.Update(ds); // this will throw exception if update(s) conflict… dbConn.Close();

// retrieve existing data set from grid…ds = (DataSet) this.dataGrid1.get_DataSource();

. . .

OleDbCommandBuilder cmdBuilder;cmdBuilder = new OleDbCommandBuilder(adapter);

dbConn.Open(); adapter.Update(ds); // this will throw exception if update(s) conflict… dbConn.Close();

Page 31: Lecture 11: Programmatic Database Access with ADO.NET

11-31MicrosoftIntroducing CS using .NETJ# in Visual Studio .NET

Summary

• Databases are a critical component of most business apps• SQL is the standard programming language for databases

• Database programming is based on framework classes– in .NET, those classes are called ADO.NET– the more you know about SQL the better