36
1 ADO.NET ed Entity Framework Vittorio Maniezzo - University of Bologna - Localserver Installando Visual Studio viene installata anche una versione di SQL Server, chiamata SQL Server Express o Localserver. Utile per sviluppo e debug. Si può installare anche indipendentemente da VS. Accessibile con qualunque strumento, fra cui: l’utility a riga di comando SqlLocalDB https://docs.microsoft.com/en-us/sql/tools/sqllocaldb-utility l’utility a riga di comando sqlcmd https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility https://docs.microsoft.com/en-us/sql/relational- databases/scripting/sqlcmd-use-the-utility SQL Server Management Studio (SSMS) https://docs.microsoft.com/en-us/sql/ssms/download-sql-server- management-studio-ssms Vittorio Maniezzo - University of Bologna 2 1 2

ADO - unibo.itisi-personale.csr.unibo.it/vittorio.maniezzo/didattica/DSS/DataBase.pdf · Prima, ma ancora adesso ODBC(Open Database Connectivity) • Assicura interoperabilità con

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

1

ADO.NETed Entity Framework

Vittorio Maniezzo - University of Bologna -

Localserver

Installando Visual Studio viene installata anche una versione di SQL Server, chiamata SQL Server Express o Localserver. Utile per sviluppo e debug. Si può installare anche indipendentemente da VS.

Accessibile con qualunque strumento, fra cui:

• l’utility a riga di comando SqlLocalDB

• https://docs.microsoft.com/en-us/sql/tools/sqllocaldb-utility

• l’utility a riga di comando sqlcmd

• https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility

• https://docs.microsoft.com/en-us/sql/relational-

databases/scripting/sqlcmd-use-the-utility

• SQL Server Management Studio (SSMS)

• https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-

management-studio-ssms

Vittorio Maniezzo - University of Bologna 2

1

2

2

SqlLocalDb

Utile soprattutto per la gestione del LocalDb, non per query. Notare che LocalDb ha diverse "istanze" al cui interno stanno i database.

sqllocaldb v – elenca le versioni SQL Express installate

sqllocaldb info – elenca le istanze utilizzabili

v11.0 = Microsoft SQL Server 2012 (11.0.3000.0)

v12.0 = Microsoft SQL Server 2014 (12.0.2000.8)

MSSqlLocalDb = Microsoft SQL Server 2016 (13.0.1601.5)

sqllocaldb info MSSQLLocalDB – tutti i dati di una istanza (pipe)

sqllocaldb s MSSQLLocalDB – per avviare una istanza bloccata sqllocaldb p MSSQLLocalDB – per bloccare una istanza attiva

sqlLocalDb create "testInst" –s – per creare ed avviare una istanza

sqlLocalDb delete "testInst" – per cancellare una istanza (bloccata)

Con l’istanza bloccata si possono copiare i file .mdf e .ldf che contengono un database di interesse interno a quella istanza.

Vittorio Maniezzo - University of Bologna 3

sqlcmd

Sqlcmd lavora su localserver via ODBC, connettendosi all'istanza attiva. Permette di inoltrare qualunque comando T-SQL a SQL Sever(express o normale) da file come fosse una stored procedure o da riga di comando.

Nel mio computer, attualmente è nella cartella:

C:\Program Files\Microsoft SQL Server\110\Tools\Binn\

sqlcmd -S (LocalDb)\MSSqlLocalDb

sqlcmd -S (LocalDb)\MSSqlLocalDb -i "c:\temp\creaDb.sql"

sqlcmd -S (LocalDb)\MSSqlLocalDb -Q "CREATE/DROP DATABASE testDb"

Per elencare tutti i db nell'istanza:sqlcmd -S (LocalDb)\MSSqlLocalDb -Q "select name from sys.databases"

Vittorio Maniezzo - University of Bologna 4

3

4

3

sqlcmd

Per caricare il db da filesqlcmd -S (LocalDB)\mssqllocaldb

Poi, dentro > USE [master]

> GO

> CREATE DATABASE [database_name] ON

> ( FILENAME = N'C:\temp\test\testDb.mdf' ),

> ( FILENAME = N'C:\temp\test\testDb_log.ldf' )

> FOR ATTACH ;

> GO

Vittorio Maniezzo - University of Bologna 5

Sqlcmd - tablesuse testDbGOIF OBJECT_ID('clienti', 'U') IS NOT NULL DROP TABLE clienti;CREATE TABLE clienti (

[PK_UID] INT NOT NULL IDENTITY(0,1) PRIMARY KEY,[id] INTEGER,[nome] NVARCHAR(MAX));

INSERT INTO clienti VALUES(1,'pippo');INSERT INTO clienti VALUES(2,'pluto');INSERT INTO clienti VALUES(3,'topolino');INSERT INTO clienti VALUES(4,'minnie');IF OBJECT_ID('ordini', 'U') IS NOT NULL DROP TABLE ordini;CREATE TABLE ordini (

[PK_UID] INT NOT NULL IDENTITY(0,1) PRIMARY KEY,[id] INTEGER,[idcliente] INTEGER,[codice] INTEGER,[descr] NVARCHAR(MAX));

INSERT INTO ordini VALUES(1,1,10,'dieci');INSERT INTO ordini VALUES(2,1,11,'undici');INSERT INTO ordini VALUES(3,1,12,'dodici');INSERT INTO ordini VALUES(4,2,20,'venti');INSERT INTO ordini VALUES(5,2,21,'ventuno');INSERT INTO ordini VALUES(6,2,22,'ventidue');INSERT INTO ordini VALUES(7,3,30,'trenta');INSERT INTO ordini VALUES(8,3,31,'trentuno');INSERT INTO ordini VALUES(9,4,40,'quaranta');INSERT INTO ordini VALUES(10,4,41,'quarantuno');INSERT INTO ordini VALUES(11,4,42,'quarantadue');INSERT INTO ordini VALUES(12,4,43,'quarantatre');INSERT INTO ordini VALUES(13,4,44,'quarantaquattro');

Vittorio Maniezzo - University of Bologna 6

5

6

4

Sqlcmd – backup e restore

Per salvare un backupSqlCmd -E -S Server_Name –Q “BACKUP DATABASE [Name_of_Database] TO DISK=’X:PathToBackupLocation[Name_of_Database].bak'”

esempio:SqlCmd -E -S MyServer –Q “BACKUP DATABASE [MyDB] TO DISK=’D:BackupsMyDB.bak'”

Per ripristinare un backupSqlCmd -E -S Server_Name –Q “RESTORE DATABASE [Name_of_Database] FROM DISK=’X:PathToBackupFile[File_Name].bak'”

esempio:SqlCmd -E -S MyServer –Q “RESTORE DATABASE [MyDB] FROM DISK=’D:BackupsMyDB.bak'”

Nota: questi per stessa istanza di SS. Per server diversi usare SSMS.

Vittorio Maniezzo - University of Bologna 7

SSMS

Possibile con nome server (localdb)\MSSQLLocalDB

SSMS molto pesante ma gratuito e potente.

Vittorio Maniezzo - University of Bologna 8

7

8

5

Esempio: anagrafica ordiniDue tabelle: clienti e ordini:

Vittorio Maniezzo - University of Bologna - 9

Clienti

id nome

1 pippo

2 pluto

3 topolino

4 minnie

Ordini

id idcliente codice descr

1 1 10 dieci

2 1 11 undici

3 1 12 dodici

4 2 20 venti

5 2 21 ventuno

6 2 22 ventidue

7 3 30 trenta

8 3 31 trentuno

9 4 40 quaranta

10 4 41 quarantuno

11 4 42 quarantadue

12 4 43 quarantatre

13 4 44 quarantaquattro

CREATE TABLE clienti

(id integer primary

key autoincrement,

nome text)

CREATE TABLE ordini (id integer primary key autoincrement,

idcliente integer, codice integer, descr text, foreign

key(idcliente) references clienti(id))

Creazione – ver. SqLite

DROP TABLE if exists clienti;

CREATE TABLE clienti(id integer primarykey autoincrement,nome text);

INSERT INTO clienti VALUES(1,'pippo');INSERT INTO clienti VALUES(2,'pluto');INSERT INTO clienti VALUES(3,'topolino');INSERT INTO clienti VALUES(4,'minnie');

DROP TABLE if exists ordini;

CREATE TABLE ordini (id integer primary key autoincrement,idcliente integer, codice integer, descr text, foreignkey(idcliente) references clienti(id));

INSERT INTO ordini VALUES(1,1,10,'dieci');INSERT INTO ordini VALUES(2,1,11,'undici');INSERT INTO ordini VALUES(3,1,12,'dodici');INSERT INTO ordini VALUES(4,2,20,'venti');INSERT INTO ordini VALUES(5,2,21,'ventuno');INSERT INTO ordini VALUES(6,2,22,'ventidue');INSERT INTO ordini VALUES(7,3,30,'trenta');INSERT INTO ordini VALUES(8,3,31,'trentuno');INSERT INTO ordini VALUES(9,4,40,'quaranta');INSERT INTO ordini VALUES(10,4,41,'quarantuno');INSERT INTO ordini VALUES(11,4,42,'quarantadue');INSERT INTO ordini VALUES(12,4,43,'quarantatre');INSERT INTO ordini VALUES(13,4,44,'quarantaquattro');

Vittorio Maniezzo - University of Bologna 10

9

10

6

ADO.NETPrima, ma ancora adesso

ODBC (Open Database Connectivity)• Assicura interoperabilità con molti DBMS• API molto comuni• Usa SQL come linguaggio di accesso ai dati

OLE DB• Ampio accesso a dati, relazionali e altro• Interfaccia di basso livello (C++), sviluppato come COM• Non limitato a SQL per leggere dati• Può usare driver ODBC

ADO (ActiveX Data Objects)• Interfaccia semplice component-based, object-oriented• Fornisce una modalità di programmazione alle OLE DB

utilizzabile al di fuori del C++

Vittorio Maniezzo - University of Bologna

ADO

ADO

ODBC Provider Simple Provider Native Provider

OLE DB Provider

ODBC

ODBC Driver

TextFile

Database Database

OLE DB Provider

Mainframe

OLE DB

Applicazione utente

Vittorio Maniezzo - University of Bologna

11

12

7

ADO.NET

ADO .NET è un’evoluzione di ADO.

ADO.NET è una collezione di classi, interfacce, strutture, e tipi che gestisce l’accesso ai dati all’interno del .NET Framework

• Queste collezioni sono organizzate in namespace:

System.Data,

System.Data.OleDb,

System.Data.SqlClient, etc.

Vittorio Maniezzo - University of Bologna

SQL Managed Provider

SQL ServerDatabase

ADO.NET Managed Providers

ADO.NET Managed Provider

ADO Managed Provider

OLE DB Provider

Database

Applicazione utente

Vittorio Maniezzo - University of Bologna

13

14

8

DataSet

SQL Server .NET

Data Provider

OLE DB .NET

Data Provider

SQL Server OLEDB source

Un data provider .net è un insieme di classi che servono a connettersi a una sorgente dati per ottenerne e modificarne i dati.

Vittorio Maniezzo - University of Bologna

Managed Provider

ADO.NET Accesso ai dati

Connesso: Forward-only, read-only

• L’applicazione invia query, poi legge i risultati e li elabora

• Oggetto DataReader

Disconnesso

• L’applicazione invia query, poi memorizza i risultati per una successiva elaborazione

• Minimizza il tempo di connessione col database

• Oggetto DataSet

Vittorio Maniezzo - University of Bologna

15

16

9

Architettura

DataSet

Command

ConnectionConnection

Command

DataReader

DBMS

Strutture dati personali

Managed

Data

Provider

Data

Store

Vittorio Maniezzo - University of Bologna

Oggetti di un data provider

Oggetto Descrizione

Connection Stabilisce una connessione con una specifica sorgente dati.

Command Esegue un comando sulla sorgente dati. Esponedei Parameters e accetta Transaction da unaConnection.

DataReader Legge uno stream di dati forward-only, read-only da una sorgente dati.

DataAdapter Riempie un DataSet e gestisce gli aggiornamenti con la sorgente dati.

Vittorio Maniezzo - University of Bologna

17

18

10

Architettura

Vittorio Maniezzo - University of Bologna

Classi ADO.NET Namespace System.Data

Contiene le classi di base di ADO.NET

Fondamentale è DataSet (disconnesso)

Supporta tutti i tipi di applicazioni

• Internet

ASP.NET

XML

• Windows forms

Contiene classi usate o derivate da managed providers

IDbConnection, IDbCommand, IDbDataReader

Vittorio Maniezzo - University of Bologna

19

20

11

Classi ADO.NET Namespace System.Data.SqlClient

Managed provider nativo per SQL Server

Classi SqlConnection, SqlCommand e SqlDataReader

Classi per

• Error handling

• Connection pooling

System.Data.SqlTypes contiene le classi per i tipi di dati SQL Server nativi

Vittorio Maniezzo - University of Bologna

Classi ADO.NET Namespace System.Data.SQLite

Managed provider nativo per sqlite

Classi SQLiteConnection, SQLiteCommand e SQLiteDataReader

Classi per

• Error handling

• Connection pooling

System.Data.SQLiteTypes contiene le classi per i tipi di dati SQL Server nativi

Vittorio Maniezzo - University of Bologna

21

22

12

Classi ADO.NET Interfaccia IDbConnection

Permette di astrarre la specifica tecnologia che si utilizza.

Crea una sessione unica con una sorgente dati

Implementata da SqlDbConnection, SQLiteConnection, OleDbConnection, …

Funzionalità

• Open, close di connessioni

• Inizio di transazioni

IDbTransaction fornisce metodi Commit e Rollback (v. dopo)

Vittorio Maniezzo - University of Bologna

Classi ADO.NET Interfaccia IDbCommand

Rappresenta una istruzione da inviare alla sorgente dati di solito, ma non necessariamente, SQL

Implementata da SQLiteCommand, SqlCommand, ...

Funzionalità

• Definisce l’istruzione da eseguire

• Esegue l’istruzione

• Passa e riceve parametri

ExecuteReader ritorna le righe,

ExecuteNonQuery non ritorna niente,

ExecuteScalar ritorna un singolo valore, il primo della prima riga della view

Vittorio Maniezzo - University of Bologna

23

24

13

Classi ADO.NET Interfaccia IDbTransaction

Vittorio Maniezzo - University of Bologna 25

Esempio di due comandi (insert e select) in un’unica transazioneusing (IDbConnection con = new SqlConnection(conString)){ try

{ con.Open();using (var transaction = con.BeginTransaction() ){ command = new SqlCommand("insert into ... ,con);

command.Transaction = transaction; // primo comando nrows = command.ExecuteNonQuery();command.CommandText = "select ... command.Transaction = transaction; // secondo comandoIDStorico=(int) command.ExecuteScalar();transaction.Commit(); // o entrambi i comandi o nessuno

}con.Close();

}

catch(Exception ex) { ...

Classi ADO.NET Interfaccia IDataReader

Accesso forward-only, read-only a stream di dati

Implementata da SqlDataReader e SQLiteDataReader, ...

Creata col metodo ExecuteReader di IDbCommand

Le operazioni sull’oggetto associato IDbConnectionsono bloccate finchè il reader non viene chiuso

Vittorio Maniezzo - University of Bologna

25

26

14

DBMS

ADO.NET, utilizzo connesso

In un contesto connesso, le risorse sono mantenute sulserver finchè non viene chusala connessione

Operazioni

1. Apri la connessione

2. Esegui un comando

3. Elabora le righe nel reader

4. Chiudi il reader

5. Chiudi la connessione

IDbConnection

IDbCommand

IDbDataReader

Vittorio Maniezzo - University of Bologna

Classi ADO.NET Esempio DataReader (SqLite)

IDbConnection conn = new SQLiteConnection(sqLiteConnString);

conn.Open();

IDbCommand com = conn.CreateCommand();

string queryText = "select id,nome from clienti";

com.CommandText = queryText;

IDataReader reader = com.ExecuteReader();

while (reader.Read())

{ view.textConsole = reader["id"]+" "+reader["nome"];

}

reader.Close();

conn.Close();

Vittorio Maniezzo - University of Bologna

27

28

15

Stringhe connessionev. http://www.connectionstrings.com/)

Sql Server

Server=myServerAddress;Database=myDataBase;User Id=myUsername;

Password=myPassword;

Esempio

connectionString = @"Data Source=tcp:137.204.74.181; Initial

Catalog=studenti;User ID=***;Password=***";

connectionString = @"Data Source=(LocalDB)\MSSQLLocalDB;Initial

Catalog = testDb;Integrated Security = True;"

SqLite (NuGet: Install-Package System.Data.SQLite)

Data Source=filename;Version=3;

Esempio

connString = @"Data Source="+dbpath+"; Version=3";

Postgres

Server=127.0.0.1;Port=5432;Database=myDataBase;User

Id=myUsername;Password=myPassword;

Esempio

connString = "Server=localhost;UID=studenti;

PWD=laPWD;Database=studenti;Port=5432;";Vittorio Maniezzo - University of Bologna

Indipendenza dalla tecnologia• Le stringhe di connessione sono gestite al meglio in un file di

config, non direttamente nel codice.

• In un progetto windows form, il config è di solito nel file App.config.

• Per inserire la gestione delle stringhe, il progetto deve referenziare l’assembly System.Configuration

L’accesso alla stringa specifica avveine con una istruzione del tipo ConfigurationManager.ConnectionStrings["SQLiteConn"].ConnectionString;

Nell’App.config si inserisce una sezione come la seguente<connectionStrings>

<add name="SQLiteConn" connectionString="Data Source=|DataDirectory|\DBFILE;Version=3;" providerName="System.Data.SQLite" />

<add name="LocalDbConn" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;Initial Catalog = testDb;Integrated Security = True;Connect Timeout=20" providerName="System.Data.SqlClient" />

</connectionStrings>

Vittorio Maniezzo - University of Bologna 30

29

30

16

IstanziazioneIn app.config:<appSettings>

<add key="dbServer" value="LocalDbConn" />

<!-- "SQLiteConn" "LocalDbConn" "RemoteSqlServConn"-->

</appSettings>

Nel costruttore della classe che istanzia:string sdb = ConfigurationManager.AppSettings["dbServer"];

switch (sdb)

{ case "SQLiteConn":

connString = ConfigurationManager.ConnectionStrings["SQLiteConn"].ConnectionString;

factory = ConfigurationManager.ConnectionStrings["SQLiteConn"].ProviderName;

break;

case "LocalDbConn":

connString = ConfigurationManager.ConnectionStrings["LocalSqlServConn"].ConnectionString;

factory = ConfigurationManager.ConnectionStrings["LocalSqlServConn"].ProviderName;

break;

. . .Vittorio Maniezzo - University of Bologna 31

Parametrized query

I commandText sono semplici stringhe SQL, spesso costruite dinamicamente. Es, where delle select, values delle insert, …

Pericolo SQL injection, e comunque opportuno un controllo dei tipi. Viene fatto con query parametrizzate, tre fasi:

1. costruzione della stringa del comando con parametri.

2. dichiarazione di un oggetto Parameter, assegnandogli i valori

richiesti.

3. assegnazione dell'oggetto Parameter alla proprietà Parameters dell'oggetto Command.

Vittorio Maniezzo - University of Bologna 32

31

32

17

Parametrized query: comando

Prima fase: costruzione di una stringa di comando che contiene dei segnaposto per i parametri.

I segnaposto saranno riempiti con i valori effettivi quando verrà eseguito il comando.

I parametri sono connotati da un '@' prefisso al nome del parametro, es:

IDbCommand com = conn.CreateCommand();

com.CommandText = “select nome from clienti”;

com.CommandText += “ where id = @id";

Vittorio Maniezzo - University of Bologna 33

Parametrized query: Parameter

Seconda fase: si definisce un'istanza di IDbDataParameter per ogni parametro nel comando, es.:

IDbDataParameter param = com.CreateParameter();

param.DbType = DbType.Int32;

param.ParameterName = "@id";

param.Value = 1;

Terza fase: assegnazione di ogni parametro alla collectionParameters del comando:

com.Parameters.Add(param);

Vittorio Maniezzo - University of Bologna 34

33

34

18

Parametrized query: esempio

Esempio completo utilizzo di query parametrica:

com.CommandText = "select nome from clienti where id=@id";

IDbDataParameter param = com.CreateParameter();

param.DbType = DbType.Int32;

param.ParameterName = "@id";

param.Value = 1;

com.Parameters.Add(param);

using (IDataReader dr = com.ExecuteReader())

{ while (dr.Read())

view.textConsole = "nome: "+ dr["nome"];

}

Vittorio Maniezzo - University of Bologna 35

Indipendenza dalla tecnologia

Vittorio Maniezzo - University of Bologna 36

Nell'esempio proposto il codice fa poco riferimento alla tecnologia utilizzata (sqlite, sql server, …).

I riferimenti sono ridotti a una riga di codice grazie all’uso diretto delle interfacce.

Un uso esplicito dei provider può risultare in maggiore efficienza ma minore flessibilità.

E’ possibile astrarsi completamente dalla tecnologia, ad es. con le DbProviderFactories contenute nel namespaceSystem.Data.Common, come nel seguito.

Oppure usare un ORM (v. ancora dopo)

35

36

19

DbProviderFactories

Vittorio Maniezzo - University of Bologna 37

Il namespace System.Data.Common definisce un insieme di classi astratte che sono implementate da tutti i provider di dati.

L'intento è quello di fornire un modo agnostico di accesso ai dati, che non faccia riferimenti diretti agli assembly dei provider ADO.NET.

La classe DbProviderFactories carica il provider di dati .NET richiesto e restituisce una classe concreta conosciuta come DbProviderFactory.

DbProviderFactory funge da factory per DbConnection, DbCommand e gli altri oggetti ADO.NET.

DbProviderFactories

Vittorio Maniezzo - University of Bologna 38

Per usare DbProviderFactories è necessario che il provider sia noto al sistema.Se non lo è bisogna inserire queste righe nell'app.config (o nel web.config).

<system.data>

<DbProviderFactories>

<remove invariant="System.Data.SQLite"/>

<add name="SQLite Data Provider" invariant="System.Data.SQLite"

description=".Net Framework Data Provider for SQLite"

type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />

</DbProviderFactories>

</system.data>

Prossimo esempio (DataSet) con DbProviderFactories (ma le si possono usare anche col DataReader).

37

38

20

Classi ADO.NET Esempio DataReader (SqLite, con provider factory)

DbProviderFactory dbFactory = DbProviderFactories.GetFactory(factory);

using (DbConnection conn = dbFactory.CreateConnection())

{

try

{

conn.ConnectionString = connString;

conn.Open();

DbCommand com = conn.CreateCommand();

com.CommandText = queryText;

DbDataReader reader = com.ExecuteReader();

while (reader.Read())

FlushText(this, reader["id"] + " " + reader["nome"]);

reader.Close();

conn.Close();

}

catch (Exception ex)

{

FlushText(this, "[dataReader] Error: " + ex.Message);

}

finally

{

if (conn.State == ConnectionState.Open) conn.Close();

}

}

Vittorio Maniezzo - University of Bologna

Classi ADO.NET DataSet

• E’ una collezione di tabelle

• Non conosce la sorgente dei dati

• Gestisce le relazioni fra le tabelle

• Potente interfaccia di programmazione (ha oggetti per tabelle, colonne, relazioni, ecc)

• Ricorda lo stato originale e corrente dei dati

• Può modificare dati e metadati

• Il formato di serializzazione nativo è XML

Vittorio Maniezzo - University of Bologna

39

40

21

Classi ADO.NET DataSet

DataSet

DataTable

DataRelation

DataRow

DataColumn

Vittorio Maniezzo - University of Bologna

Classi ADO.NET Interfaccia IDataAdapter

• Riempie o aggiorna una tabella di un DataSet

• Implementata da IDbDataAdapter

• Contiene 4 oggetti predefiniti per operazioni sul dataset: Select, Insert, Update e Delete

• Se solo in lettura, si può riutilizzare lo stesso dataAdapter per leggere tabelle successive, se serve sincronizzare tabelle del dataset, si deve usare un dataAdapter diverso per ogni tabella.

Vittorio Maniezzo - University of Bologna

41

42

22

ADO.NET utilizzo disconnessoIn un contesto disconnesso, le risorse NON sono gestite sulserver quado i dati vengonoelaborati

Operazioni

1. Apri la connessione

2. Riempi il DataSet

3. Chiudi la connessione

4. Elabora il DataSet

5. Apri la connessione

6. Aggiorna la sorgente dati

7. Chiudi la connessione

IDbConnection

IDbDataAdapter

DataSet

DBMS

Vittorio Maniezzo - University of Bologna

Classi ADO.NET DataTable

Oggetto in memoria che rappresenta una tabella

• Colonne

• Righe

Schema definito dalla collection Columns

Integrità dati gestita dall’oggetto Constraint

Eventi pubblici

• Modifica/cancellazione righe

• Modifica colonne

Vittorio Maniezzo - University of Bologna

43

44

23

Classi ADO.NET DataColumn

Elemento fondamentale di un DataTable (contenuto nella collection Columns)

Definisce quali tipi di dati possono entrare (per mezzo della proprietà DataType)

Altre proprietà: AllowNull, Unique e ReadOnly

Può contenere Constraints (una collection su DataTable)

Può contenere Relations (collection su DataSet)

Vittorio Maniezzo - University of Bologna

Classi ADO.NET DataRow

Rappresenta i dati in una DataTable (contenuto nella collection Rows)

Conforme allo schema definito da DataColumns

Proprietà per determinare lo stato di una riga (new, changed, deleted ecc.)

Vittorio Maniezzo - University of Bologna

45

46

24

Classi ADO.NET DataRelation

Correla due DataTables via DataColumns

I valori di DataType delle due DataColumnsdevono essere identici

Le modifiche non corrispondenti alla relazione sono proibite

Vittorio Maniezzo - University of Bologna

DataSet

DataRelation

DataRelationCollection

DataTableCollection

DataSet

DataTable

DataRowCollection

DataColumnCollection

DataView

DataRow

DataColumn

Vittorio Maniezzo - University of Bologna

47

48

25

Classi ADO.NET Esempio DataSet (SqLite, con provider factory)

DataSet ds = new DataSet();

ConnectionStringSettings connString = ConfigurationManager.ConnectionStrings["SQLiteConn"];

DbProviderFactory dbFactory = DbProviderFactories.GetFactory("System.Data.SQLite");

using (DbConnection conn = dbFactory.CreateConnection())

{

try

{ conn.ConnectionString = connString.ConnectionString;

conn.Open();

DbDataAdapter dbAdapter = dbFactory.CreateDataAdapter();

DbCommand dbCommand = conn.CreateCommand();

dbCommand.CommandText = "select id,nome from clienti";

dbAdapter.SelectCommand = dbCommand;

dbAdapter.Fill(ds);

ds.Tables[0].TableName = "clienti";

foreach(DataRow dr in ds.Tables["clienti"].Rows)

view.textConsole = dr["nome"].ToString();

}

catch (Exception ex)

{ view.textConsole = "[FillDataSet] Error: " + ex.Message;

}

finally

{ if (conn.State == ConnectionState.Open) conn.Close();

}

}

Vittorio Maniezzo - University of Bologna

DataView

• Una DataView permette di creare viste diverse sui

dati memorizzati in una DataTable.

• Con una DataView si possono visualizzare i dati di

una tabella con ordinamenti diversi, o filtrarli in

base ai loro valori.

Vittorio Maniezzo - University of Bologna

49

64

26

DataGrid e DataView

string sQueryString = "SELECT * FROM test";

SQLiteDataAdapter myDSAdapter = new SQLiteDataAdapter();

DataSet myDataSet = new DataSet();

myDSAdapter.SelectCommand = new SQLiteCommand(sQueryString, conn);

myDSAdapter.Fill(myDataSet);

DataTable Cart = new DataTable();

Cart = myDataSet.Tables[0];

DataView CartView = new DataView(Cart);

dg.DataSource = CartView;// per collegare a un dataGridView

Vittorio Maniezzo - University of Bologna

Object Relational Mapping (ORM)

Vittorio Maniezzo - University of Bologna

65

66

27

Tecnologie ORM

Object-Relational Mapping (ORM) è una tecnica di

programmazione per associare e convertire automaticamente dei dati fra tabelle di database e classi/oggetti OO

ORM crea una sorta di database a oggetti utilizzabile da codici a oggetti come C# o Java

I framework ORM (object-relational persistence

frameworks) automatizzano il processo ORM.

Vittorio Maniezzo - University of Bologna

ORM Framework

I framework ORM tipicamente forniscono le seguenti funzionalità:

• Creazione di un object model dal database schema

• Creazione di un database schema dall'object model

• Query dei dati via object-oriented API

• Manipolazione dati CRUD: create, retrieve, update, delete

I framework ORM generano automaticamente query SQL per effettuare le operazioni richieste sui dati

Vittorio Maniezzo - University of Bologna

67

68

28

ORM Mapping – EsempioEsempio di mapping per un sottinsieme del database Northwind

schema database relazionale

ORM Entities (Classi C#)

ORM

Framework

Vittorio Maniezzo - University of Bologna

Entity Framework e ADO.NET

• Entity Framework (EF) è un framework ORM open source, parte di .NET

• Fornisce una infrastruttura run-time per gestire dati in database SQL come oggetti .NET

• Lo schema del database relazionale è associato a un modello a oggetti (object model)

• Visual Studio contiene dei tool per generare le associazioni (Entity Framework SQL data mapping).

• I data mapping consistono di classi C# e di XML

• Esistono anche altri ORM per .net: DataObjects.Net, NHibernate, OpenAccess, SubSonic ecc. ,

Vittorio Maniezzo - University of Bologna

69

70

29

Entity Framework e ADO.NET

Permette di:

• Generare classi dal modello

• Aggiornare le classi se il modello cambia

• Gestire le connessioni al database

• Effettuare le query sul modello, non sul database

• Tradurre le query al modello a query al database

• Gestire cambiamenti agli oggetti del modello

• Gestire update al database

Vittorio Maniezzo - University of Bologna

Entity Framework: Architettura

Vittorio Maniezzo - University of Bologna

72

73

30

EF: componenti architettura

Vittorio Maniezzo - University of Bologna 75

EDM (Entity Data Model): consiste di tre component:

• Conceptual Model: contiene le classi del modello e le loro relazioni. Non dipende direttamente dal database.

• Storage Model: è il modello della struttura del database, incude tabelle, viste, stored procedures, oltre cherelazioni e chiavi (primarie, esterne, … ).

• Mapping: contiene le informazioni su come gli elementidel modello concettuale sono correlate a quelli dellostorage.

EF: componenti architettura

Vittorio Maniezzo - University of Bologna 76

Interrogazione, può avvenire con tre modalità:

• LINQ to Entities: LINQ to Entities è un linguaggio di query che può interrogare l’object model. Ritorna delleentità, definite nel modello concettuale.

• Entity SQL: Entity SQL è un altro linguaggio di query, molto simile a sql, che permette di lavoraredirettamente su collezioni di entità.

POCO, Plain Old CLR Objects (!), lavora sulle collezionidi entità dell’object model con gli operatori c# standard.

75

76

31

EF: componenti architettura

Vittorio Maniezzo - University of Bologna 77

Object Service: è l’entry point del codice utente per accedere aidati del database. È responsabile della materializzazione dei dati, cioè della conversion dei dati ricevuti dal livello sottostante in entità strutturate come da modello.

Entity Client Data Provider: converte le richieste (L2E, Entity SQL, POCO) in query SQL da passare al database. Comunica con ilprovider ADO.Net che fa da interfaccia al database.

ADO.Net Data Provider: comunica con il database usando ADO.Net.

Sia VS2017 che EF6 sono tecnologie recenti e la loro integrazione con strumenti non MicroSoft non è ancora molto robusta (con SQL server pochi problemi).

Per accedere al database SqLite con EF6 da VisualStudio 2017 procedure come segue.

1 – Installare la versione SqLite adeguata.

2 – Controllare che fra le reference del progetto ci sia Entity Framework. Se non c'è, installarla via NuGet (manage packages for solution).

3 – Reference (copia) di System.Data.SQLite.dll, System.Data.SQLite.EF6.dll, System.Data.SQLite.Linq.dll

4 – Controllare che in app.config fra i provider ci sia<providers>

<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />

VS2017 e EF6: definizione del progetto

Vittorio Maniezzo - University of Bologna

77

78

32

VS2017 e EF6: definizione del progetto

Vittorio Maniezzo - University of Bologna 79

5 – In VS2017, clickare col destro sul progetto (in solution explorer) e selezionare “aggiungi / Nuovo elemento”.

6 – Dal wizard dell’Add new item, selezionare “ADO.NET Entity Data Model”. Questo attiva il wizard dell’Entity data model.

7 – Selezionare “Entity framework designer da database”

8 – selezionare “Nuova connessione”

9 - selezionare il provider per SQLite (se non c’è è stato installato ilprovider sbagliato. Tornare al passo 1).

10 -cliccare su browse e selezionare il file sqlite da utilizzare.

11 -selezionare gli elementi del database da includere nel modello

12 - fine, il modello viene generato automaticamente

Entity Data Model (EDM)

Vittorio Maniezzo - University of Bologna 80

I passi precedenti hanno portato alla creazione di un modello (io Model1), contenuto in un file xml Model1.emdx e visualizzato in solution explorer.

Il designer mostra la struttura del modello.Questa vista in realtà è basata sul file xml, checontiene le tre sezioni principali SSDL (storage model), CSDL (conceptual model) e C-S mapping.

Anche il file app.config vienemodificato aggiornando le sezioniopportune (configSections, startup, connectionStrings,

entityFramework)

79

80

33

Model browser

Vittorio Maniezzo - University of Bologna 81

Cliccando col destro sul diagramma del modelloconcettuale si può aprire il model browser.

Il model browser mostra questi elementi:

• Diagrammi: i diagrammi visuali dell’EDM.

• Tipi di Entità: lista di tutte le classi (tipi) mappati sulletabelle del DB.

• Tipi complessi: Classi generate dall’ EDM come risultato di stored procedures, funzioni che generanotabelle, ecc.

• Tipi enum: lista di tutte le entità usate come enumdall’ entity framework.

• Associazioni: relazioni foreign key fra entità.

• Importazioni di funzioni: funzioni che sarannomappate sulle stored procedures, ecc. E cje quindisaranno usate come funzioni dall’ EF.

• esempioModel.Store: lo schema del database (SSDL).

Approcci progettuali

Vittorio Maniezzo - University of Bologna 82

Tre modalità secondo cui definire il modulo EF:

1. Database First

Si ipotizza di avere già il database completo, e si generano le entità sulla base del db: si genera l’EDMX, cioè le classi EDM, il dbContext e le entità da un database esistente.

2. Code First

Si scrivono per prime le classi POCO che definiscono il dominio e quindi si crea database da queste classi per rendere persistenti i dati.

3. Model First

Si creano entità, relazioni e gerarchie di ereditarietà direttamente sull'area di progettazione di EDMX, nel designer, e quindi si generano le classi e il database dal modello.

81

82

34

DbContext

Vittorio Maniezzo - University of Bologna 83

Creando un EDM viene generata una classe (qui esempioEntities) che specializza la DbContext nel

modello corrente.

Questa classe è il collegamento fra il codice e il DB. È responsabile di:

• EntitySet: contiene un entity set (DbSet<TEntity>) per tutte le entità chesono mappate su tabelle del db.

• Query: converte le query L2E, … , in SQL e le inoltra al database.

• Change Tracking: memorizza i cambiamenti subiti dale entità dopoessere state lette dal DB.

• Persisting Data: Esegue Insert, Update e Delete sul DB in funzione dellostato dele entità.

• Caching: delle entità lette.

• Gestione delle relazioni: responsabile del controllo delle relazioni.

• Object Materialization: converte i dati delle tabelle in oggetti (entità).

DbSet

Vittorio Maniezzo - University of Bologna 84

La classe DBSet rappresenta un insieme di entità che viene utilizzato per creare, leggere, aggiornare ed eliminare dati. Usando DBContext è possibile ottenere il riferimento di DBSet, es. context.ordini o context.clienti

Intuitivamente, il DbContextcorrisponde al database (o a una collezione di tabelle e viste del database) e il DbSet corrisponde a una tabella o vista. Si usa un oggetto DbContext per accedere alle tabelle e viste, che saranno rappresentate da DbSet, e i DbSet per accedere, creare, aggiornare, cancellare e modificare i dati delle tabelle.

83

84

35

Metodi del DbSet (i principali)

Vittorio Maniezzo - University of Bologna 85

Metodo Descrizione

Add(Entity)Aggiunge una entità al context, in stato added. Viene passata sul db con SaveChanges diventando unchanged.context.ordini.Add(newOrder)

Attach(Entity)Aggiunge una entità al context, in stato unchanged. Non verrebbe passata su db.context.ordini.Attach(newOrder)

CreateCrea una nuova istanza dell’entità corrispondente al tipo del set e ne restituisce il puntatore. L’istanza non è inserita nel set.var newOrder = context.ordini.Create();

Find(int)Una la chiave primaria per trovare una entità, provando prima sul context, se non la trova sul db. ordini O = context.ordini.Find(maxOrderId2);

Remove(Entity)Segna l’entità coma Deleted, verrà cancellata dal database con SaveChanges.context.ordini.Remove(O);

SqlQueryQuery diretta: SQL che interroga il db e ritorna entità del set. var ordList = context.ordini.SqlQuery("select * from ordini where id > 10").ToListAsync();

Esempio utilizzo DbSettestDbEntities context = new testDbEntities (connString);

// select

foreach (ordini o in context.ordini)

view.textConsole = o.descr;

// insert

ordini newOrder = new ordini();

newOrder.idcliente = 4;

...

context.ordini.Add(newOrder);

context.SaveChanges();

// update, si passa la primary key del record da aggiornare

ordini O = context.ordini.Find(maxOrderId2);

O.descr = "boh";

context.SaveChanges();

// delete, si passa il puntatore al record da cancellare

O = context.ordini.Find(maxOrderId);

context.ordini.Remove(O);

context.SaveChanges();

Vittorio Maniezzo - University of Bologna 86

85

86

36

Interrogazioni dirette al db(raw queries)

Vittorio Maniezzo - University of Bologna 87

SQL query per collezioni entità (using System.Linq):Il metodo SQLQuery() del DBSet permette di scrivere SQL queries che ritornano istanze di entità. using (var context = new testDbEntities () )

{ var lstOrdini = context.ordini.SqlQuery("Select * from ordini").ToList();

}

SQL query per tipi base (non entità), non serve Linq:Se la query SQL ritorna tipi base, non entità, si può usare il metodo SqlQuery sulla classe Database.Esempio per recuperare un interousing (var ctx = new testDbEntities ())

{ maxOrderId =

ctx.Database.SqlQuery<int>("Select max(PK_UID) from ordini").FirstOrDefaultAsync().Result;

}

Altri comandi SQL al database:Il metodo ExecuteSqlCommnad serve a inviare comandi non-query al database (Insert, Update o Delete)

using (var ctx = new testDbEntities ())

{

//Update

int numUpdated =

ctx.Database.ExecuteSqlCommand(@"Update clienti set nome ='nuovo nome' where id=1");

//Insert

int numInserted =

ctx.Database.ExecuteSqlCommand(@"insert into clienti(nome) values('nuovo cliente')");

//Delete

int numDeleted = ctx.Database.ExecuteSqlCommand("delete from clienti where id>4");

}

87