ADO.NET, i Data Provider e
l'architettura connessa
Silvano Coriani
Developer & Platform Evangelism
MCTrainer
MCSDeveloper
MCADeveloper
MCSEInternet
MCDBA
1 / 70
Da dove iniziare...
2 / 70
Agenda
3 / 70
.NET Data Access Overview
4 / 70
.NET Application
DataSet
System.Data.Oracle
System.Data.SqlClient
System.Data.OleDb
System.Data.Odbc
OLE DB
OLE DB Provider
ODBC
Oracle
SQL Server
Other DBMS
Non-relational
sources
5 / 70
.NET Data Provider
• System.Data
6 / 70
.NET Data Provider
• connessaCommand
7 / 70
.NET Data Provider
• DataAdapter
• DataReader
8 / 70
ADO.NET e SQL Server 2000
9 / 70
SqlClient .NET Data Provider
10 / 70
SqlClient Managed Provider
• Non utilizza direttamente i cursori server
di SQL Server
– Nel caso, occorrono comandi T-SQL espliciti
(OPEN CURSOR, sp_cursor, sp_executesql ecc.)
– Oppure utilizzare ADO 2.x attraverso COM
Interop
• Permette di interagire con le funzionalità
XML di SQL Server 2000
– ExecuteXmlReader()
11 / 70
SqlClient .NET Data Provider Object Model
SqlConnection
SqlCommand
System.Xml.XmlReader
SqlDataReader
SqlParameterCollection
Object
SqlParameter
12 / 70
SqlClient e il CLR
Common Language Runtime
SqlClient
TDS
Parser
SqlServer
13 / 70
Accesso ai dati nel database
server
14 / 70
Query ad-hoc
15 / 70
Prepare / Execute
• PreparedSqlCommand
16 / 70
sp_executesql
• Alternativa valida alle stored procedure
– Elimina la gestione lato server
• Se si vuole ottenere il riutilizzo del piano di
esecuzione, anche qui occorre definire
correttamente I parametri con il relativo
tipo
• Eseguita in modalità RPC
– Più efficiente nell’esecuzione sul server
– Riutilizzo del piano di esecuzione della query
exec sp_executesql N‘Insert T1 Values (@p)’,N’@p float’,1
17 / 70
Stored Procedure
• WITH RECOMPILE
18 / 70
Stored Procedure
• SqlCommandCommandType
– Definizione di tutti i parametri tipizzati
utilizzati dalla stored procedure
– MAI
19 / 70
Classica Stored Procedure
CREATE PROC spGetCustomerOrders
@CustomerID int
@NumOrder int OUTPUT
AS
-- Validazione di parametri di input
...
-- Logica applicativa (eventualmente chiama altre SP)
...
-- Restituzione di uno o più result set
...
-- Restituisco il valore di ritorno
20 / 70
Stored Procedure FOR XML
CREATE PROC spGetCustomerOrdersXML
@CustomerID int
@NumOrder int OUTPUT
AS
-- Validazione di parametri di input
...
-- Logica applicativa (eventualmente chiama altre SP)
...
-- Restituzione di uno o più result set
SELECT
C.CustomerID,O.OrderID,O.OrderDate
FROM
Customer C Left Join Orders O ON C.CustomerID=O.CustomerID
WHERE
C.CustomerID = @CustomerID
FOR XML AUTO, ELEMENTS –- o EXPLICIT
-- Restituisco il valore di ritorno
21 / 70
Posso passare un set di record ad una SP?
CREATE PROC spInsertCustomersXML
@RecordSetXML varchar(1024)
AS
-- Carico il doc XML nel DOM
sp_xml_preparedocument @h OUTPUT, @ RecordSetXML
-- Eseguo un inserimento in una tabella filtrando
-- le informazioni che mi servono attraverso XPath
OpenXML(@h,'//Customer')
WITH (CustomerID varchar(5) '@ID',
CompanyName varchar(32),'@name')
-- Rimuovo il documento dalla memoria
sp_xml_removedocument
22 / 70
SQL Server 2000 Best Practices
23 / 70
Cursori
• row-based
– set
24 / 70
SqlConnection
• IDbConnection
• ConnectionStringSqlCommandSqlDataReader
– Close()Dispose()
• BeginTransaction
– SqlTransaction
25 / 70
SqlConnection
• AttachDBFilenameSqlClientPermission
26 / 70
SqlConnection
• SqlCommandSqlDataAdapter
[Visual Basic]
Dim nwindConn As SqlConnection = New SqlConnection("Data _
Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")
nwindConn.Open()
[C#]
SqlConnection nwindConn = new SqlConnection("Data Source=localhost; Integrated
Security=SSPI; Initial Catalog=northwind");
nwindConn.Open();
27 / 70
SqlCommand
28 / 70
SqlCommand
• Implementa l’interfaccia IDbCommand
– ExecuteReader()
• Da utilizzare quando è previsto un result set come
ritorno
– ExecuteScalar()
• Da utilizzare per aggregazioni o risultati di calcoli
• Ritorna solo la prima colonna della prima riga, gli altri
dati vengono persi
– ExecuteNonQuery()
• Ottimizzato per query che non ritornano result set ma
solo parametri di ritorno o numero di record modificati
– ExecuteXmlReader()
29 / 70
SqlCommand e query libere
Dim sqlConn As SQLConnection
Dim sqlCmd As SQLCommand
Dim rowsAffected As Integer
Try
' Creo la connessione
sqlConn = New SQLConnection(myConnString)
' Creo il comando
sqlCmd = New SQLCommand()
' specifico il tipo di comando
With sqlCmd
.CommandType = CommandType.Text
.CommandText = "Insert Customers (Alias, CustomerName) _
Values ('myAlias','myName')"
.Connection = sqlConn
End With
' apro la connessione
sqlConn.Open()
' eseguo il comando, vengono ritornate le righe inserite
rowsAffected = sqlCmd.ExecuteNonQuery()
Catch e As Exception
' gestisco l’eccezione …
Finally
' chiudo la connesione
sqlConn.Close()
End Try
30 / 70
SqlCommand e le Stored
Procedure
• Parameters
31 / 70
SqlCommand e le Stored
Procedure
• ExecuteReader()DataReader
• DBNull.Value per impostare a null un
parametro di input di una SP
• CommandBehavior
32 / 70
SqlCommand e le Stored
Procedure
sqlConn = New SQLConnection(myConnString)
' Create a new command object
sqlCmd = New SQLCommand()
' Specify the stored procedure and connection
With sqlCmd
.CommandType = CommandType.StoredProcedure
.CommandText = "InsertCustomer"
.Connection = sqlConn
End With
' Define and add a parameter to the parameters collection
param = sqlCmd.Parameters.Add(New SQLParameter("@p", SQLDBType.NVarChar, 100)
With param
.Direction = ParameterDirection.Input
' Set the parameter value
.Value = “xyz"
End With
' Add remaining parameters
…
' Open the connection
sqlConn.Open()
' Execute the command
rowsAffected = sqlCmd.ExecuteNonQuery()
33 / 70
SqlDataReader
• SqlCommand
• Read()IEnumerable
34 / 70
SqlDataReader
• IDataReaderIDataRecord
– Per accesso a informazioni in formato
rettangolare e non
• È possibile accedere ai dati nelle singole
colonne per indicenome del campo o
attraverso metodo accessori dedicati ai
tipi di dato contenuti
– GetDateTime()GetDouble()GetGuid(),
GetInt32()
35 / 70
SqlDataReader
• NextResult()
• La struttura del result set è descritta
attraverso una “schema table”
– GetSchemaTable()
36 / 70
Utilizzo di SqlDataReader
[Visual Basic]
Dim myReader As SqlDataReader = myCommand.ExecuteReader()
Do While myReader.Read()
Console.WriteLine(vbTab & "{0}" & vbTab & "{1}", myReader.GetInt32(0),
myReader.GetString(1))
Loop
myReader.Close()
[C#]
SqlDataReader myReader = myCommand.ExecuteReader();
while (myReader.Read())
Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));
myReader.Close();
37 / 70
XmlReader
• ExecuteXmlReader() FOR XML
[Visual Basic]
Dim custCMD As SqlCommand = New SqlCommand("SELECT * FROM Customers FOR XML _
AUTO, ELEMENTS", nwindConn)
Dim myXR As System.Xml.XmlReader = custCMD.ExecuteXmlReader()
[C#]
SqlCommand custCMD = new SqlCommand("SELECT * FROM Customers FOR XML AUTO,
ELEMENTS", nwindConn);
System.Xml.XmlReader myXR = custCMD.ExecuteXmlReader();
38 / 70
Operazioni di Data Definition
Language
• ExecuteNonQuery()
39 / 70
Transazioni in ADO.NET
• Transazioni locali
– All’interno del codice SQL delle Stored Procedure
• BEGIN/COMMIT TRAN
– SqlOleDbTransaction
40 / 70
Transazioni in ADO.NET
[C#]
SqlConnection conn = new SqlConnection();
conn.Open("...");
SqlTransaction tx = conn.BeginTransaction();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "...";
cmd.Transaction = tx;
cmd.ExecuteNonQuery();
tx.Commit();
[VB.NET]
OleDbConnection conn = new OleDbConnection();
conn.Open("...");
OleDbTransaction tx = conn.BeginTransaction();
OleDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "...";
cmd.Transaction = tx;
cmd.ExecuteNonQuery();
tx.Commit();
41 / 70
Error & Info handling
• Errori durante l’esecuzione di operazioni
sulla fonte dati vengono intercettati
attraverso le eccezioni
• Ogni Managed providers implementa le
proprie eccezioni
– SqlException
• SqlError
42 / 70
Error & Info handling
• SqlInfoMessageEventHandlerInfoMessa
ge
43 / 70
Error & Info handling
public static int Main(string[] args) {
try
{
SqlConnection conn = new SqlConnection(“ConnectionString”);
// Associo un event handler all’evento di InfoMessage
conn.InfoMessage += new SqlInfoMessageEventHandler(myHandler);
conn.Open();
}
catch (SqlException e) {
for (int i=0; i < e.Errors.Count; i++)
{
Console.WriteLine("Index #" + i + "\n Error: " + e.Errors[i].ToString() + "\n");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{ conn.Close(); }
return 0;
}
44 / 70
Error & Info handling
public static void myHandler(object conn, SqlInfoMessageEventArgs e)
{
Console.WriteLine("caught a SQL warning");
for (int i=0; i < e.Errors.Count; i++)
{
Console.WriteLine("Index#" + i + "\n" + "Warning:" + e.Errors[i].ToString() +
"\n");
}
}
45 / 70
Considerazioni sulle
performance
• Dispose()DataReader
46 / 70
Considerazioni sulle
performance
• FOR XMLXmlReader
47 / 70
Considerazioni sulle
performance
• Tenere sempre presente il tipo di
comando e di valori di ritorno
– Singola entità letta per chiave primaria
• Stored Procedure con parametri di ritorno
– Valore scalare
• ExecuteScalar()
– DataReader
48 / 70
Codice portabile tra più Data Provider
49 / 70
Integrare applicazioni .NET con altri database
server
50 / 70
OleDb Managed Provider
51 / 70
OleDb Managed Provider
Provider
OleDb
Managed
Provider
OLEDB
Common Language Runtime
Data Source
Relazionale
e non
52 / 70
OLEDB Managed Provider Object
Model
OleDbConnection
.CreateCommand
.ExecuteReader
OleDbCommand
.Connection
.Parameters
OleDbDataReader
.Item
Object
OleDbParameterCollection
.Add
.Item
.CreateParameter
.OleDbParameter
53 / 70
OleDbConnection
[Visual Basic]
Dim myConnection As String = "Provider=SQLOLEDB;Data Source=localhost;Initial _
Catalog=Northwind;Integrated Security=SSPI;"
Dim myConn As New OleDbConnection(myConnection)
myConn.Open()
[C#]
String myConnection = "Provider=SQLOLEDB;Data Source=localhost;Initial
Catalog=Northwind;Integrated Security=SSPI;";
OleDbConnection myConn = new OleDbConnection(myConnection);
myConn.Open();
54 / 70
OleDbCommand
public void ReadMyData(string myConnString)
{
string mySelectQuery = "SELECT OrderID, CustomerID FROM Orders";
OleDbConnection myConnection = new OleDbConnection(myConnString);
OleDbCommand myCommand = new OleDbCommand(mySelectQuery,myConnection);
myConnection.Open();
OleDbDataReader myReader = myCommand.ExecuteReader();
try
{
while (myReader.Read())
{Console.WriteLine(myReader.GetInt32(0) + ", " + myReader.GetString(1));}
}
finally
{
// da chiudere sempre dopo aver terminato la lettura
myReader.Close();
// da chiudere sempre dopo aver terminato la lettura
myConnection.Close();}
}
55 / 70
ODBC Managed Provider
56 / 70
ODBC Managed Provider
Driver
Odbc
Managed
Provider
ODBC
Common Language Runtime
Data Source
Relazionale
57 / 70
ODBC Managed Provider Object
Model
OdbcConnection
.CreateCommand
.ExecuteReader
OdbcCommand
.Connection
.Parameters
OdbcDataReader
.Item
Object
OdbcParameterCollection
.Add
.Item
.CreateParameter
OdbcParameter
58 / 70
OleDbDataReader
• ExecuteReader()
59 / 70
Utilizzo di OleDbDataReader
Public Sub ReadMyData(myConnString As String)
Dim mySelectQuery As String = "SELECT OrderID, CustomerID FROM Orders"
Dim myConnection As New OleDbConnection(myConnString)
Dim myCommand As New OleDbCommand(mySelectQuery, myConnection)
myConnection.Open()
Dim myReader As OleDbDataReader
myReader = myCommand.ExecuteReader()
' La chiamata a Read posiziona sul primo record
While myReader.Read()
Console.WriteLine(myReader.GetInt32(0).ToString() + ", " _
+ myReader.GetString(1))
End While
' chiudere il reader
myReader.Close()
' chiudere la connessione
myConnection.Close()
End Sub
60 / 70
DB2 e ADO.NET
Application
Application
Application
System.Data.OleDb
Microsft.Data.ODBC
IBM.Data.DB2
OLE DB .Net
Data Provider
ODBC .Net Data
Provider
DB2 .Net Data
Provider
OleDbConnection
OdbcConnection
DB2Connection
OleDbCommand
OdbcCommand
DB2Command
OleDbAdapter
OdbcDataAdapter
DB2DataAdapter
OleDbDataReader
OdbcDataReader
DB2DataReader
IBM DB2 OLE
DB Provider
IBM DB2 ODBC
Driver
DB2
61 / 70
DB2Connection Object
62 / 70
DB2Command Object
63 / 70
DB2DataReader Object
64 / 70
Oracle e .NET
• Microsoft .NET Data Provider per Oracle
– Prodotto da Microsoft
– Usa gli strumenti client di Oracle
• Oracle Data Provider per .NET (ODP.NET)
– Sviluppato da Oracle
– Integrazione completa
– Espone tutte le caratteristiche di un Oracle DB
• Oracle Connect per .NET
65 / 70
.NET Data Providers
66 / 70
ODP.NET
DataSet
Oracle
DataAdapter
OracleCommand
Builder
Oracle
DataReader
Oracle
Command
Oracle
Transaction
Oracle
Connection
67 / 70
ODP.NET
68 / 70
In Sintesi
69 / 70
Link utili
70 / 70
News
71 / 70
72 / 70
Scarica

ADO.NET, i Data Provider e l`architettura connessa