12. Programmatic Database Access with ADO.NET

Download Report

Transcript 12. Programmatic Database Access with ADO.NET

Lecture 11:
Programmatic Database
Access with ADO.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
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-2
Part 1
• Architecture of ADO.NET…
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-3
Relational technology
• ADO.NET is designed to access relational databases
• Example:
– Sales database with customers, orders, and products
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-4
Architecture
• ADO.NET architecture based on data providers
– data providers encapsulate DB-specific details
.NET Programmer
ADO.NET
Data Provider
DB
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-5
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.
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-6
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
System.Data
provider-neutral
System.Data.Common
SQL Server
System.Data.SqlClient
other DBs, e.g. MS Access
System.Data.OleDb
ODBC (Open Database Connectivity)
System.Data.Odbc
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-7
Part 2
• Basic database access…
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-8
Overview of database access
• Three steps:
1. open connection to database
2. execute SQL to retrieve records / update DB
3. close connection
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-9
(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)
import System.Data.*;
import System.Data.OleDb.*;
String sConnection;
sConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=Sales.mdb";
connection
OleDbConnection dbConn;
dbConn = new OleDbConnection(sConnection);
dbConn.Open();
MessageBox.Show(dbConn.get_State().toString());
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-10
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
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-11
(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
OleDbDataReader
dbCmd;
dbReader;
command
dbCmd = new OleDbCommand(sql, dbConn);
dbReader = dbCmd.ExecuteReader();
while ( dbReader.Read() )
{
}
connection
data reader
record
record
record
// 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);
field name of data value in current record
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-12
(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();
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-13
Part 3
• Data-driven application design…
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-14
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
{
.
.
.
}
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-15
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
OleDbDataReader
dbConn = null;
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();
}
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-16
Part 4
• Updating a database…
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-17
Executing action queries
• Use action queries when you need to modify a DB
– updates
– inserts
– deletes
• Execute action queries via ExecuteNonQuery method…
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-18
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();
dbConn.Close();
// returns # of rows affected…
if (rows != 1) // sanity check to make sure it worked...
throw new System.Exception("Query ran but failed to update DB?!");
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-19
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
Customer
fn, ln;
c;
c = this.listBox1.get_SelectedItem();
fn = c.firstName;
ln = c.lastName;
sql = "...";
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-20
Dynamic string building
• Dynamic SQL requires dynamic string building
• Example:
– build dynamic SQL to delete selected customer…
String
sql;
sql = String.Format("Delete From Customers Where " +
"FirstName='{0}' And LastName='{1}';",
fn, ln);
– don't forget the delimiters for strings & dates!
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-21
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);
MessageBox.Show("Deleted!");
// update GUI!
}
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-22
Oops!
• Try to delete "O'Dahl, Kathie"…
• What happens?
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-23
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);
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-24
Part 5
• DataSets…
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-25
DataSets
• DataSets are an in-memory data structure
– easily filled with data from a database
– easily passed around
– easily displayed in a GUI app
DataAdapter
DataSet
Name
Price
Ants
$ 0.49
5000
Birds
$ 4.49
500
Cats
$29.95
100
Dogs
$79.95
20
Command
Connection
DB
Stock
"Table"
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
• DataSet mirrors the database
– data forms a temporary table called
"Table" within DataSet
11-26
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);
Name
Price
Stock
Ants
$ 0.49
5000
Birds
$ 4.49
500
Cats
$29.95
100
Dogs
$79.95
20
"Table"
dbConn.Open();
adapter.Fill(ds);
dbConn.Close();
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-27
DataGrid display
• DataSet can be bound to DataGrid control for easy display
– one line of code!
.
.
.
this.dataGrid1.SetDataBinding(ds, "Table");
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-28
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…
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-29
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);
dbConn.Close();
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
// this will throw exception if update(s) conflict…
11-30
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
Introducing
Microsoft
J#
in Visual Studio
CS using
.NET
.NET
11-31