Sei sulla pagina 1di 58

ADO.

NET
What Will We cover

• Understand the difference between ADO and


ADO.NET

• How to integrate ADO.NET with .NET


applications using Visual Studio.NET

• How to use ADO.NET’s capabilities


– Single table select/update
– Stored procedures select/update
– Multiple table select/update

• How to take advantage of XML support with


ADO.NET
Today’s Distributed Systems
Presentation Tier
• Presentation
Tier
Business Tier
• Business Tier ADO ADO
Recordset Recordset

• Data Tier

Data Tier

OLE DB
rowset
Agenda

• Introduction to ADO.NET
• Programming Fundamentals
• ADO.NET and XML
• ADO and ADO.NET - Comparison
• When to Use What
• Tips, Tricks, And Commonly Asked Questions
• Summary
Introduction to ADO.NET
Why ADO.NET?

• To Accommodate Web Application Model

– Loosely coupled

– Maintaining state between requests

– Uses HTTP
What is ADO.NET?
• Natural Evolution of ADO

• Interoperability

• Integrated with .NET Framework

• Data Model for ASP.NET

• Scalability
Programming Fundamentals
ADO.NET Architecture
ADO.NET

DataSet

DataAdapter DataReader

Connection Command

Parameters
Managed Provider
Managed Providers
• Namespaces -Which to use

SqlClient Managed-Provider OleDb Managed-Provider


Namespace Namespace
What happened to RecordSet?

• In ADO
– RecordSet
• In ADO.NET
– DataReader
• Connected, non-cached, FO/RO RecordSet
– DataSet
• Disconnected, cached, scrollable data
– DataAdapter
• Logic for populating the DataSet and propagating changes
back to the datasource
Connection

• Represents A Connection To The Data Source

• On A Connection, You Can…


– Begin, commit, and abort transactions

• Equivalent To The ADODB.Connection Object


Connection Example
// Create and open an SqlConnection
SqlConnection cnn = new
SqlConnection("server=localhost;uid=sa;pwd=;database=nort
hwind");
cnn.Open();

// Optionally Start a Transaction


SqlTransaction txn = cnn.BeginTransaction();

// Do work…
if(TransferFunds(fromAct, toAct, Amount) == true) // succeeded
txn.Commit();
else
txn.Rollback();

cnn.Close(); // Always Close Connection


Command Object

• Represents A Command To Be Executed

• With A Command You Can:


– Define a Sql statement to be executed on the database
server
– Set parameter information for the procedure
– Retrieve return values from command execution

• Corresponds To ADODB.Command Object


Executing Commands

• Methods
– ExecuteNonQuery

– ExecuteReader

– ExecuteScalar

– ExecuteXmlReader
Command Example
// command using stored procedure
string strCon =
“server=(local);uid=user;pwd=password;database=Northwind”;
SqlConnection myConnection = new SqlConnection(strCon);
// Create Instance of Connection and Command Object
SqlCommand myCommand = new SqlCommand("OrdersList",
myConnection);
// Mark the Command as a SPROC
myCommand.CommandType = CommandType.StoredProcedure;
// Add Parameters to SPROC
SqlParameter parameterCustomerid = new
SqlParameter("@CustomerID", SqlDbType.Int, 4);
parameterCustomerid.Value = Int32.Parse(customerID);
myCommand.Parameters.Add(parameterCustomerid);
// Execute the command
myConnection.Open()
SqlDataReader result =
myCommand.ExecuteReader(CommandBehavior.CloseConnection);
Demo Command Object
Data Reader

• Alternative to DataAdapter/DataSet

• Connected

• Read only

• Forward only
DataReader Example

string strCon = “server=(local);uid=user;pwd=password;


database=Northwind”;
string strSqlQuery = “select name,companyname from cust”;
SqlConnection myConnection = new SqlConnection(strCon);
myConnection .Open()
SqlCommand objcommand = new
SqlCommand(strSqlQuery,objConnection);
SqlDataReader objReader objComman.ExecuteReader();
while(objReader.Read)
{
//do the necessary operation
}
objReader.Close();
Demo DataReader Object
DataAdapter

• Loads a table from a data DataSet

store and writes changes back.


Fill() Update()
– Exposes two methods:
SelectCommand
• Update(DataSet,DataTable) InsertCommand
• Fill(DataSet,DataTable) UpdateCommand
DeleteCommand
Mappings
Mappings
Mappings
DataAdapter

Data
store

– Allows single DataSet to be populated from multiple


different datasources
DataSet
• In Memory Store For Client Data

• Relational View of Data


– Tables, Columns, Rows,
Constraints, Relations

• Directly create metadata and insert data


– directly inserting data using DataTable

• Explicit Disconnected Model


– Disconnected, remotable object
– No knowledge of data source or properties
– Array-like indexing
– Strong Typing
DataSet

DataSet DataSet DataTable


Tables
Table
Columns
Column
DataColumn
Constraints
Constraint
DataTable Rows

Relations
Row DataRow
Relation

Relations Constraints

XML Schema
Fill DataSet with DataAdapter

//fill dataset with data adapter

string strCon = “server=(local);uid=user;pwd=password;


database=Northwind”;
SqlConnectoin objConnection = new SqlConnection(strCon);
string strSqlQuery = “select name,companyname from cust”;
SqlDataAdapter objAdapter = new
SqldataAdapter(strSqlQuery,objConnection);
DataSet ds = new DataSet()
objAdapter.Fill(ds,”Customers”);
Fill DataSet with DataTable
// fill dataset with datatable

DataTable dt = new DataTable();


DataRow dr;
dt.Columns.Add( new DataColumn( ”Name", typeof( string ) ) );
dt.Columns.Add( new DataColumn( ”Age", typeof( string ) ) );
for(int I=0;I<3;I++)
{
dr = dt.NewRow();
dr[0] = “Allen”
dr[1] = “22”;
dt.Rows.Add(dr);
}
DataSet ds = new DataSet();
ds.Tables.Add(dt);
DataRelation in DataSet
//datarelation in dataset
Ds.Table.Add(CreateBuildingTable());
Ds.Table.Add(CreateRoomTable());
Ds.Relations.Add(“Rooms”,Ds.Tables[“Building”].Columns[“BuildingI
D”],
Ds.Tables[“Room”].Columns[“BuildingID”]);

Building
BuildingID Room
Name RoomId
Name
BuildingID
foreach(DataRow theBuilding in Ds.Tables[“Building”].Rows)
{ DataRow[] children = theBuilding.GetChildRows(“Rooms”);
int roomCount = children.Length;
// do necessary operations
foreach(DataRow theRoom in children)
Console.WriteLine(theRoom[“Name”]);
}
DataConstraint in dataset
//dataconstraint in dataset
//creates primary key for a table
public static void pk_table(DataTable dt)
{
DataColumn[] pk = new DataColumn[1];
pk[0] = dt.Columns[“ProductID”];
dt.PrimaryKey = pk;
}
Using DataSet as a Cache

private DataSet GetCategories() {


//See if DataSet exists in Cache
DataSet categories;
categories = (DataSet)Cache["CategoriesDS"];

if (categories == null) { // not in cache

//Create DataAdapter and Load DataSet


SqlDataAdapter adapter = new SqlDataAdapter(
"Select CategoryName from Categories",cnn);
adapter.Fill(categories);

// Put Categories Dataset into Cache


Cache["CategoriesDS"]=categories;
}
}
Demo DataAdapter and DataSet
WebForms DataBinding
<%@ Import Namespace="System.Data.SqlClient" %>
<html><head><script language="C#" runat=server>

public void Page_Load(Object sender, EventArgs e) {

// Create a SqlCommand and Get a DataReader


SqlConnection cnn = new SqlConnection("server=localhost;uid=sa;");
cnn.Open();
SqlCommand cmd = new SqlCommand("Select * from customers", cnn);
SqlDataReader results = cmd.ExecuteReader();

// Bind to Results
ActivityList.DataSource = results;
ActivityList.DataBind(); }

</script></head><body>
<asp:DataGrid id="ActivityList" runat="server"/>
</body></html>
Winforms Databinding
// Create a Parameterized SqlCommand
SqlCommand cmd = new SqlCommand("GetAccountInfo", cnn);
cmd.CommandType=CommandType.StoredProcedure;
cmd.Parameters.Add("@A_ID",accountID);

// Populate DataSet with results


DataSet account = new DataSet;
DataAdapter adapter = new DataAdapter(cmd);
adapter.Fill(account);

// Create WinForm DataGrid and Bind to Results


DataGrid accountGrid = new DataGrid();
accountGrid.SetDataBinding(myDataSet, "AccountList");
ADO.NET and XML
Controls, Transforms
Designers, XSL/T, X-Path,
Code-gen, etc etc

Caching
DataSet XmlData-
Sync Document

DataAdapter DataReader
Access XmlReader
Command XmlText- XmlNode-
Connection Reader Reader
Managed Provider
XML in ADO.NET
• DataSet
– Loads/saves XML data into/out of DataSet
– Schema can be loaded/saved as XSD
– Schema can be inferred from XML Data
• XmlDataDocument
– Exposes relational view over structured XML
– Allows strong typing, control binding, relational access of
XML data
– Allows XML tools (schema validation, XSL/T, XPath
queries) against relational data
– Preserves full fidelity of XML Document
Loading XML
// Load DataSet with XML
DataSet ds = new DataSet();
ds.ReadXml("inventory.xml");

// Add a record to the Inventory table


DataTable inventory = ds.Tables["Inventory"];
DataRow row = inventory.NewRow();
row["TitleID"]=1;
row["Quantity"]=25;
inventory.Rows.Add(row);

// Write out XML


ds.WriteXml("updatedinventory.xml");
Loading Schema From XML
myDataSet.ReadXmlSchema(schemaFile);
– ComplexTypes mapped to Tables
– Nested ComplexTypes mapped to Related Tables
– Key/Unique constraints mapped to
UniqueConstraints
– KeyRef mapped to ForeignKeyConstraint
Mapping Schema To Relational Data
<xsd:element name="Orders" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="OrderID" type="xsd:int"/>
<xsd:element name="OrderDetails" minOccurs="0"
maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ProductID" type="xsd:int"/>
<xsd:element name="UnitPrice" type="xsd:number"/>
<xsd:element name="Quantity" type="xsd:short"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="OrderDate" type="xsd:dateTime"
minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="CustomerID" type="xsd:string"
use="prohibited" />
</xsd:complexType>
</xsd:element>
Mapping Schema To Relational Data
<xsd:element name="Orders" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="OrderID" type="xsd:int"/>
<xsd:element name="OrderDetails" minOccurs="0"
Orders
maxOccurs="unbounded">
<xsd:complexType> OrderID OrderDate CustomerID
<xsd:sequence>
<xsd:element name="ProductID" type="xsd:int"/>
<xsd:element name="UnitPrice" type="xsd:number"/>
<xsd:element name="Quantity" type="xsd:short"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="OrderDate" type="xsd:dateTime"
minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="CustomerID" type="xsd:string"
use="prohibited" />
</xsd:complexType>
</xsd:element>
Mapping Schema To Relational Data
<xsd:element name="Orders" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="OrderID" type="xsd:int"/>
<xsd:element name="OrderDetails" minOccurs="0"
maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ProductID" type="xsd:int"/>
<xsd:element name="UnitPrice" type="xsd:number"/>
<xsd:element name="Quantity" type="xsd:short"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element> OrderDetails
<xsd:element name="OrderDate" type="xsd:dateTime"
minOccurs="0"/> ProductID UnitPrice Quantity OrderID
</xsd:sequence>
<xsd:attribute name="CustomerID" type="xsd:string"
use="prohibited" />
</xsd:complexType>
</xsd:element>
Schema Inference
• If no schema is defined when you call
DataSet.ReadXml(), schema will be inferred from
the data
• General Rules
– Element becomes table if:
• It repeats, or
• It contains more than simple content
• …Otherwise, it becomes column
– Attributes become columns
– Relations are created for nested table-mapped elements
• Hidden columns created for parent/child relationship
• Useful for ad-hoc binding to data
XmlDataDocument
• The DataSet can be associated with
an XmlDataDocument
– Exposes a relational view over
structured XML
• According to the DataSet schema
– Allows strong typing, control binding, relational access of
XML data
– Allows XML tools (schema validation, XSL/T, XPath queries)
against relational data
– Preserves full fidelity of XML Document
Demo XML Samples
ADO and ADO.NET
Comparison

Features ADO ADO.NET


Memory Resident Uses the Recordset object Uses the DataSet object, which can
Data Representation which looks like a single contain one or more tables, represented
table by DataTable objects

Relationships between Requires the JOIN query to Supports the DataRelation object to
multiple tables assemble data from associate rows in one DataTable object
multiple database tables in with rows in another DataTable object.
a single result table.

Data visitation Scans RecordSet rows Uses a navigation paradigm for non-
sequentially sequential access to rows in a table.
Follows relationships to navigate from
rows in one table to corresponding rows
in another table.
Disconnected access Provided by the Communicates to a database with
RecordSet but standardized calls to the DataAdapter
typically supports object, which communicates to an OLE DB
connected access, provider, or directly to SQL Server.
represented by the
Connection object.
You communicate to a
database with calls to
an OLE DB provider.

Cursors Utilizes server-side and The architecture is disconnected so cursors


client-side cursors. are not applicable.

Programmability Uses the Connection Uses the strongly typed programming


object to transmit characteristic of XML. Data is self-describing
commands that because names for code items correspond to
address underlying the "real world" problem solved by the code.
data structure of a Underlying data constructs such as tables,
data source. rows, and columns do not appear, making
code easier to read and to write.
Sharing disconnected data Uses COM marshalling to Transmits a DataSet as XML.
between tiers or components transmit a disconnected record The XML format places no
set. This supports only those restrictions on data types and
data types defined by the COM requires no type conversions.
standard. Requires type
conversions, which demand
system resources.

Transmitting data through Problematic, because firewalls Supported, because ADO.NET


firewalls are typically configured to DataSet objects use XML,
prevent system-level requests which can pass through
such as COM marshalling. firewalls.

Scalability Database locks and active Disconnected access to


database connections for long database data without
durations contend for limited retaining database locks or
database resources. active database connections
for lengthy periods limits
contention for limited
database resources.
When To Use What?
Considerations

• Connected Data Access

• Disconnected Data Access

• XML View of Relational Data


When To Use What?
Connected Data Access

• Managed Providers
– Connection, Transaction
• Connecting to DataSource
• Starting/Ending Transactions
– Command, Parameters
• Database Updates, Selects, DDL
– DataReader
• (FO/RO) Server Cursor
– DataAdapter
• Pushing data into Dataset
• Reading changes out of DataSet
When To Use What?
Disconnected Data Access
• DataSet
– Application Data
– Remoting Results
• SOAP, Remoting
– Caching Results
• ASP.NET Cache
– Persisting results
• Save Data as XML, Schema as XSD
– User interaction
• Scrolling, sorting, filtering
– DataView, DataViewManager
• Binding Windows controls
When To Use What?
XML Data Access
• XML
– XmlDocument
• XmlDataDocument
• Implements the W3C DOM level 1 and 2 core
– XPathNavigator
• Provides read-only random access
– XslTransform
• Supports XSLT 1.0 syntax
Tips, Tricks, And Commonly Asked
Questions
Refreshing Data In The DataSet
• Issue: Want to update DataSet with results from
server which may have changed since DataSet was
populated
• Solution:
– Use Adapter.Fill() to update current values
• Fill will update existing values if you have a Primary key
– To update original values but preserve changes
• Fill a new DataSet and use DataSet.Merge() with
PreserveChanges=true
DataSet source = {some source};
DataSet dest1 = source.Copy();
DataSet dest2 = source.Clone();
DataSet dest3 = source.GetChanges();
Retrieving Multiple Tables Into Dataset

• Issue: Want to populate multiple tables in the


DataSet in a single round-trip to the Database
• Solution:
– Use Batch SQL/Stored Procedures to return multiple results

SqlDataAdapter adapter = new SqlDataAdapter(


"SELECT * FROM customers; SELECT * FROM orders",cnn);
adapter.Fill(DataSet);
Naming Tables Returned
As Multiple Results
• Issue: Multiple results populated into DataSet are
mapped to tables named “Table1”, “Table2”, etc.
• Solution:
– Define TableMappings for returned results

SqlDataAdapter adapter = new SqlDataAdapter(


"SELECT * FROM customers; SELECT * FROM orders",cnn);

adapter.TableMappings.Add("Table1","Customer");
adapter.TableMappings.Add("Table2","Orders");

adapter.Fill(DataSet);
Passing Nulls As Parameter Values

• Issue: I can’t seem to pass a null value as a


parameter to my stored procedure. I’ve tried not
setting it, setting it to Null (nothing in VB), setting
it to empty string (“”) and I can’t get it to work.
• Solution:
– Use DBNull.Value

SqlParameter param = new SqlParameter();


param.Value = DBNull.value;
Closing The Connection When Finished With A
Datareader
• Issue: Passing a DataReader to another routine
needs to close the Connection when the
DataReader is closed.
• Solution:
– Use CommandBehavior.CloseConnection

private DataReader getCategories() {


SqlCommand cmd = new SqlCommand( "Select * from
Categories, cnn);
DataReader results =
cmd.ExecuteReader(CommandBehavior.CloseConnection);

return results;
}
Summary
• Integrated into the Framework

• Optimized for the web

– Disconnected support
– Choice of data access
– Xml everywhere
– Fast

Potrebbero piacerti anche