Creazione di un livello di accesso ai dati (C#)

di Scott Mitchell

Scarica il PDF

In questa esercitazione si inizierà dall'inizio e si creerà il livello di accesso ai dati (DAL), usando dataset tipizzato, per accedere alle informazioni in un database.

Introduzione

Come sviluppatori Web, la nostra vita ruota attorno all'uso dei dati. Vengono creati database per archiviare i dati, il codice per recuperarlo e modificarlo e le pagine Web da raccogliere e riepilogarlo. Questa è la prima esercitazione in una serie lunga che esaminerà le tecniche per implementare questi modelli comuni in ASP.NET 2.0. Si inizierà con la creazione di un'architettura software composta da un livello di accesso ai dati (DAL) usando Set di dati tipizzato, un livello BLL (Business Logic Layer) che applica regole business personalizzate e un livello di presentazione composto da pagine ASP.NET che condividono un layout di pagina comune. Dopo aver disposto questo lavoro back-end, verrà illustrato come visualizzare, riepilogare, raccogliere e convalidare i dati da un'applicazione Web. Queste esercitazioni sono adattate per essere concise e fornire istruzioni dettagliate con un sacco di schermate per illustrare visivamente il processo. Ogni esercitazione è disponibile nelle versioni C# e Visual Basic e include un download del codice completo usato. Questa prima esercitazione è abbastanza lunga, ma il resto viene presentato in blocchi molto più digeribili.

Per queste esercitazioni si userà una versione di Microsoft SQL Server 2005 Express Edition del database Northwind inserita nella directory App_Data. Oltre al file di database, la cartella App_Data contiene anche gli script SQL per la creazione del database, nel caso in cui si vuole usare una versione del database diversa. Se si usa una versione diversa SQL Server del database Northwind, è necessario aggiornare l'impostazione NORTHWNDConnectionString nel file di Web.config dell'applicazione. L'applicazione Web è stata creata usando Visual Studio 2005 Professional Edition come progetto di sito Web basato su file system. Tuttavia, tutte le esercitazioni funzioneranno altrettanto bene con la versione gratuita di Visual Studio 2005, Visual Web Developer.

In questa esercitazione si inizierà dall'inizio e si creerà il livello di accesso ai dati (DAL), seguito dalla creazione del livello di logica di business (BLL) nella seconda esercitazione e si userà il layout e lo spostamento della pagina nel terzo. Le esercitazioni dopo la terza si creeranno sulla base impostata nella prima tre. Abbiamo molto da coprire in questa prima esercitazione, quindi apriamo Visual Studio e iniziamo!

Passaggio 1: Creazione di un progetto Web e connessione al database

Prima di poter creare il livello di accesso ai dati (DAL), è prima necessario creare un sito Web e configurare il database. Iniziare creando un nuovo sito Web basato su file system ASP.NET. A tale scopo, passare al menu File e scegliere Nuovo sito Web, visualizzando la finestra di dialogo Nuovo sito Web. Scegliere il modello di sito Web ASP.NET, impostare l'elenco a discesa Percorso su File System, scegliere una cartella per posizionare il sito Web e impostare la lingua su C#.

Creare un nuovo file System-Based sito Web

Figura 1: Creare un nuovo sito Web System-Based file (fare clic per visualizzare l'immagine full-size)

Verrà creato un nuovo sito Web con una pagina Default.aspx ASP.NET e una cartella App_Data .

Con il sito Web creato, il passaggio successivo consiste nell'aggiungere un riferimento al database in Esplora server di Visual Studio. Aggiungendo un database a Esplora server, è possibile aggiungere tabelle, stored procedure, visualizzazioni e così via da Visual Studio. È anche possibile visualizzare i dati della tabella o creare query personalizzate tramite mano o graficamente tramite Query Builder. Inoltre, quando si compilano i set di dati tipiti per il dal servizio dati, è necessario puntare Visual Studio al database da cui devono essere costruiti i dataset tipiti. Anche se è possibile fornire queste informazioni di connessione in quel momento, Visual Studio popola automaticamente un elenco a discesa dei database già registrati in Esplora server.

I passaggi per l'aggiunta del database Northwind a Esplora server dipendono dal fatto che si vuole usare il database SQL Server 2005 Express Edition nella cartella App_Data o se si dispone di un'installazione del server di database Microsoft SQL Server 2000 o 2005 che si desidera usare.

Uso di un database nella cartella App_Data

Se non si dispone di un server di database SQL Server 2000 o 2005 a cui connettersi o si vuole semplicemente evitare di dover aggiungere il database a un server di database, è possibile usare la versione SQL Server 2005 Express Edition del database Northwind che si trova nella cartella App_Data del sito Web scaricato (NORTHWND). MDF).

Un database inserito nella cartella App_Data viene aggiunto automaticamente a Esplora server. Supponendo di avere installato SQL Server 2005 Express Edition nel computer, verrà visualizzato un nodo denominato NORTHWND. MDF in Esplora server, che è possibile espandere ed esplorare le tabelle, le visualizzazioni, le stored procedure e così via (vedere la figura 2).

La cartella App_Data può contenere anche file di .mdb di Microsoft Access, che, come le loro controparti SQL Server, vengono aggiunti automaticamente a Esplora server. Se non si vuole usare alcuna delle opzioni di SQL Server, è sempre possibile installare il database e le app Northwind Traders e accedere alla directory App_Data. Tenere presente, tuttavia, che i database di Accesso non sono più ricchi di funzionalità come SQL Server e non sono progettati per essere usati negli scenari del sito Web. Inoltre, un paio di esercitazioni su 35+ utilizzeranno alcune funzionalità a livello di database che non sono supportate da Access.

Connessione al database in un server di database microsoft SQL Server 2000 o 2005

In alternativa, è possibile connettersi a un database Northwind installato in un server di database. Se il server di database non ha già installato il database Northwind, è prima necessario aggiungerlo al server di database eseguendo lo script di installazione incluso nel download di questa esercitazione.

Dopo aver installato il database, passare a Esplora server in Visual Studio, fare clic con il pulsante destro del mouse sul nodo Data Connections e scegliere Aggiungi connessione. Se esplora server non viene visualizzato, passare alla visualizzazione/Esplora server oppure premere CTRL+ALT+S. Verrà visualizzata la finestra di dialogo Aggiungi connessione, in cui è possibile specificare il server a cui connettersi, le informazioni di autenticazione e il nome del database. Dopo aver configurato correttamente le informazioni di connessione al database e fare clic sul pulsante OK, il database verrà aggiunto come nodo sotto il nodo Data Connections. È possibile espandere il nodo del database per esplorare le tabelle, le visualizzazioni, le stored procedure e così via.

Aggiungere una connessione al database Northwind del server di database

Figura 2: Aggiungere una connessione al database Northwind del server di database

Passaggio 2: Creazione del livello di accesso ai dati

Quando si utilizzano dati un'opzione consiste nell'incorporare la logica specifica dei dati direttamente nel livello di presentazione (in un'applicazione Web, le pagine ASP.NET costituiscono il livello di presentazione). Ciò può assumere la forma di scrittura di codice ADO.NET nella parte del codice della pagina di ASP.NET o usando il controllo SqlDataSource dalla parte di markup. In entrambi i casi, questo approccio associa strettamente la logica di accesso ai dati con il livello di presentazione. L'approccio consigliato, tuttavia, consiste nell'separare la logica di accesso ai dati dal livello di presentazione. Questo livello separato viene definito livello di accesso dati, DAL per breve e viene in genere implementato come progetto di libreria di classi separato. I vantaggi di questa architettura a livelli sono ben documentati (vedere la sezione "Ulteriori letture" alla fine di questa esercitazione per informazioni su questi vantaggi) ed è l'approccio che verrà adottato in questa serie.

Tutto il codice specifico dell'origine dati sottostante, ad esempio la creazione di una connessione al database, l'emissione di comandi SELECT, INSERT, UPDATE e DELETE e così via deve trovarsi nel DAL. Il livello di presentazione non deve contenere riferimenti a tale codice di accesso ai dati, ma deve invece effettuare chiamate a DAL per qualsiasi e tutte le richieste di dati. I livelli di accesso ai dati in genere contengono metodi per accedere ai dati del database sottostante. Il database Northwind, ad esempio, include tabelle Prodotti e categorie che registrano i prodotti per la vendita e le categorie a cui appartengono. Nel nostro DAL saranno disponibili metodi come:

  • GetCategories(), che restituirà informazioni su tutte le categorie
  • GetProducts(), che restituirà informazioni su tutti i prodotti
  • GetProductsByCategoryID(categoryID), che restituirà tutti i prodotti appartenenti a una categoria specificata
  • GetProductByProductID(productID), che restituirà informazioni su un determinato prodotto

Questi metodi, quando richiamati, si connettono al database, rilasciano la query appropriata e restituiscono i risultati. Come restituiscono questi risultati è importante. Questi metodi potrebbero semplicemente restituire un DataSet o DataReader popolato dalla query di database, ma idealmente questi risultati devono essere restituiti usando oggetti fortemente tipizzati. Un oggetto fortemente tipizzato è un oggetto il cui schema è definito rigidamente in fase di compilazione, mentre l'opposto, un oggetto tipizzato in modo libero, è uno il cui schema non è noto fino a quando non viene eseguito il runtime.

Ad esempio, DataReader e DataSet (per impostazione predefinita) sono oggetti tipizzati in modo libero poiché lo schema è definito dalle colonne restituite dalla query di database usata per popolarle. Per accedere a una determinata colonna da una tabella DataTable di tipo libero, è necessario usare la sintassi come DataTable. Rows[index]["columnName"]. La digitazione libera di DataTable in questo esempio viene visualizzata dal fatto che è necessario accedere al nome della colonna usando un indice stringa o ordinale. Una tabella dati fortemente tipizzata, d'altra parte, avrà ognuna delle relative colonne implementate come proprietà, risultante dal codice simile a DataTable. Righe[indice].columnName.

Per restituire oggetti fortemente tipizzati, gli sviluppatori possono creare oggetti business personalizzati o usare DataSet tipizzati. Un oggetto business viene implementato dallo sviluppatore come classe le cui proprietà in genere riflettono le colonne della tabella di database sottostante rappresentata dall'oggetto business. Un DataSet tipizzato è una classe generata da Visual Studio in base a uno schema di database e i cui membri sono fortemente tipizzato in base a questo schema. DataSet tipizzato è costituito da classi che estendono le classi DataSet, DataTable e DataRow ADO.NET. Oltre a datatable fortemente tipizzato, i dataset tipizzato ora includono anche TableAdapter, che sono classi con metodi per popolare le tabelle DataTable di DataSet e propagando le modifiche all'interno delle tabelle DatiTables tornare al database.

Nota

Per altre informazioni sui vantaggi e sugli svantaggi dell'uso di DataSet tipizzati rispetto agli oggetti business personalizzati, vedere Progettazione di componenti livello dati e passaggio di livelli di dati.

Per queste esercitazioni verranno usati dataset fortemente tipizzato. La figura 3 illustra il flusso di lavoro tra i diversi livelli di un'applicazione che usa Set di dati tipizzato.

Tutto il codice di accesso ai dati viene retrocesso al DAL

Figura 3: Tutto il codice di accesso ai dati viene retrocesso al dal (fare clic per visualizzare l'immagine a dimensioni complete)

Creazione di un dataset tipizzato e di una scheda tabella

Per iniziare a creare IL DAL, si inizia aggiungendo un DataSet tipizzato al progetto. A questo scopo, fare clic con il pulsante destro del mouse sul nodo del progetto nel Esplora soluzioni e scegliere Aggiungi un nuovo elemento. Selezionare l'opzione DataSet nell'elenco dei modelli e denominarla Northwind.xsd.

Scegliere di aggiungere un nuovo dataset al progetto

Figura 4: scegliere di aggiungere un nuovo set di dati al progetto (fare clic per visualizzare l'immagine a dimensioni complete)

Dopo aver fatto clic su Aggiungi, quando viene richiesto di aggiungere DataSet alla cartella App_Code , scegliere Sì. Il Designer per Il set di dati tipizzato verrà quindi visualizzato e verrà avviata la Configurazione guidata TableAdapter, consentendo di aggiungere il primo TableAdapter al DataSet tipizzato.

Un dataset tipizzato funge da raccolta fortemente tipizzata di dati; è costituito da istanze DataTable fortemente tipizzate, ognuna delle quali è a sua volta composta da istanze DataRow fortemente tipizzate. In questa serie di esercitazioni verrà creata una tabella DataTable fortemente tipizzata per ognuna delle tabelle di database sottostanti da usare. Si inizierà con la creazione di una tabella DataTable per la tabella Products .

Tenere presente che le tabelle DataTable fortemente tipizzate non includono informazioni su come accedere ai dati dalla tabella di database sottostante. Per recuperare i dati per popolare DataTable, viene usata una classe TableAdapter, che funziona come livello di accesso ai dati. Per Products DataTable, TableAdapter conterrà i metodi GetProducts(), GetProductByCategoryID(categoryID)e così via verrà richiamato dal livello presentazione. Il ruolo di DataTable consiste nel fungere da oggetti fortemente tipizzati usati per passare i dati tra i livelli.

La Configurazione guidata TableAdapter inizia richiedendo di selezionare il database da usare. Nell'elenco a discesa vengono visualizzati i database in Esplora server. Se al momento non è stato aggiunto il database Northwind a Esplora server, è possibile fare clic sul pulsante Nuova connessione.

Scegliere Il database Northwind dall'elenco Drop-Down

Figura 5: Scegliere il database Northwind dall'elenco Drop-Down (fare clic per visualizzare l'immagine a dimensione intera)

Dopo aver selezionato il database e aver fatto clic su Avanti, verrà chiesto se salvare il stringa di connessione nel file Web.config. Salvando il stringa di connessione si evita di impostarlo come hardcoded nelle classi TableAdapter, semplificando le operazioni se le informazioni stringa di connessione cambiano in futuro. Se si sceglie di salvare il stringa di connessione nel file di configurazione inserito nella <sezione connectionStrings>, che può essere crittografato facoltativamente per migliorare la sicurezza o modificato in un secondo momento tramite la nuova pagina delle proprietà ASP.NET 2.0 all'interno dello strumento Amministrazione GUI di IIS, che è più ideale per gli amministratori.

Salvare la stringa di connessione in Web.config

Figura 6: Salvare la stringa di connessione inWeb.config (fare clic per visualizzare l'immagine a dimensione intera)

Successivamente, è necessario definire lo schema per il primo Oggetto DataTable fortemente tipizzato e fornire il primo metodo da usare per TableAdapter durante il popolamento di DataSet fortemente tipizzato. Questi due passaggi vengono eseguiti contemporaneamente creando una query che restituisce le colonne della tabella che si desidera riflettere nell'oggetto DataTable. Alla fine della procedura guidata verrà assegnato un nome di metodo a questa query. Al termine dell'operazione, questo metodo può essere richiamato dal livello presentazione. Il metodo eseguirà la query definita e popola una DataTable fortemente tipizzata.

Per iniziare a definire la query SQL, è prima necessario indicare come si vuole che TableAdapter esegua la query. È possibile usare un'istruzione SQL ad hoc, creare una nuova stored procedure o usare una stored procedure esistente. Per queste esercitazioni si useranno istruzioni SQL ad hoc.

Eseguire query sui dati usando un'istruzione SQL ad hoc

Figura 7: Eseguire una query sui dati usando un'istruzione SQL ad hoc (fare clic per visualizzare l'immagine a dimensione intera)

A questo punto è possibile digitare manualmente la query SQL. Quando si crea il primo metodo nell'oggetto TableAdapter, in genere si desidera che la query restituisca le colonne che devono essere espresse nell'oggetto DataTable corrispondente. A tale scopo, è possibile creare una query che restituisce tutte le colonne e tutte le righe della tabella Products :

Immettere la query SQL nella casella di testo

Figura 8: Immettere la query SQL nella casella di testo (fare clic per visualizzare l'immagine a dimensione intera)

In alternativa, usare Generatore query e costruire graficamente la query, come illustrato nella figura 9.

Creare graficamente la query tramite il Editor di query

Figura 9: Creare graficamente la query tramite il Editor di query (fare clic per visualizzare l'immagine a dimensione intera)

Dopo aver creato la query, ma prima di passare alla schermata successiva, fare clic sul pulsante Opzioni avanzate. Nei progetti di siti Web , "Genera istruzioni Insert, Update e Delete" è l'unica opzione avanzata selezionata per impostazione predefinita; se si esegue questa procedura guidata da una libreria di classi o da un progetto Windows, verrà selezionata anche l'opzione "Usa concorrenza ottimistica". Lasciare deselezionata l'opzione "Usa concorrenza ottimistica". Si esaminerà la concorrenza ottimistica nelle esercitazioni future.

Selezionare solo l'opzione Genera istruzioni Insert, Update e Delete

Figura 10: selezionare solo l'opzione Genera istruzioni Inserisci, Aggiorna ed Elimina (fare clic per visualizzare l'immagine a dimensione intera)

Dopo aver verificato le opzioni avanzate, fare clic su Avanti per passare alla schermata finale. In questo caso viene chiesto di selezionare i metodi da aggiungere all'oggetto TableAdapter. Esistono due modelli per popolare i dati:

  • Compilare una tabella DataTable con questo approccio viene creato un metodo che accetta un oggetto DataTable come parametro e lo popola in base ai risultati della query. La classe ADO.NET DataAdapter, ad esempio, implementa questo modello con il relativo metodo Fill().
  • Restituisce un oggetto DataTable con questo approccio, il metodo crea e riempie automaticamente l'oggetto DataTable e lo restituisce come valore restituito dai metodi.

È possibile che TableAdapter implementi uno o entrambi questi modelli. È anche possibile rinominare i metodi forniti qui. Lasciare selezionate entrambe le caselle di controllo, anche se verranno usate solo le ultime esercitazioni. Si rinomina anche il metodo GetData piuttosto generico in GetProducts.

Se selezionata, la casella di controllo finale " GenerateDBDirectMethods" crea i metodi Insert(), Update() e Delete() per TableAdapter. Se si lascia deselezionata questa opzione, tutti gli aggiornamenti dovranno essere eseguiti tramite il solo metodo Update() di TableAdapter, che accetta l'oggetto DataSet tipizzato, un Oggetto DataTable, un singolo DataRow o una matrice di DataRows. Se è stata deselezionata l'opzione "Genera istruzioni Insert, Update e Delete" dalle proprietà avanzate nella figura 9 questa impostazione della casella di controllo non avrà alcun effetto. Lasciare selezionata questa casella di controllo.

Modificare il nome del metodo da GetData a GetProducts

Figura 11: Modificare il nome del metodo da GetData a GetProducts (fare clic per visualizzare l'immagine a dimensione intera)

Completare la procedura guidata facendo clic su Fine. Dopo la chiusura della procedura guidata, viene restituito il Designer DataSet che mostra l'oggetto DataTable appena creato. È possibile visualizzare l'elenco di colonne in Products DataTable (ProductID, ProductName e così via), nonché i metodi di ProductsTableAdapter (Fill() e GetProducts()).

L'oggetto Products DataTable e ProductsTableAdapter è stato aggiunto al dataset tipizzato

Figura 12: L'oggetto Products DataTable e ProductsTableAdapter è stato aggiunto al dataset tipizzato (fare clic per visualizzare l'immagine a dimensione intera)

A questo punto è disponibile un DataSet tipizzato con una singola dataTable (Northwind.Products) e una classe DataAdapter fortemente tipizzata (NorthwindTableAdapters.ProductsTableAdapter) con un metodo GetProducts(). Questi oggetti possono essere usati per accedere a un elenco di tutti i prodotti dal codice, ad esempio:

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
    new NorthwindTableAdapters.ProductsTableAdapter();
Northwind.ProductsDataTable products;
products = productsAdapter.GetProducts();
foreach (Northwind.ProductsRow productRow in products)
    Response.Write("Product: " + productRow.ProductName + "<br />");

Questo codice non richiedeva la scrittura di un bit di codice specifico dell'accesso ai dati. Non è stato necessario creare un'istanza di alcuna classe ADO.NET, non è stato necessario fare riferimento ad alcuna stringa di connessione, query SQL o stored procedure. TableAdapter fornisce invece il codice di accesso ai dati di basso livello.

Ogni oggetto usato in questo esempio è anche fortemente tipizzato, consentendo a Visual Studio di fornire IntelliSense e il controllo dei tipi in fase di compilazione. Oltre a tutte le tabelle DataTable restituite dal TableAdapter, è possibile associare ASP.NET controlli Web dati, ad esempio GridView, DetailsView, DropDownList, CheckBoxList e molti altri. Nell'esempio seguente viene illustrato l'associazione di DataTable restituita dal metodo GetProducts() a un controllo GridView in solo tre righe di codice all'interno del gestore eventi Page_Load .

AllProducts.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AllProducts.aspx.cs"
    Inherits="AllProducts" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>View All Products in a GridView</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h2>
            All Products</h2>
        <p>
            <asp:GridView ID="GridView1" runat="server"
             CssClass="DataWebControlStyle">
               <HeaderStyle CssClass="HeaderStyle" />
               <AlternatingRowStyle CssClass="AlternatingRowStyle" />
            </asp:GridView>
             </p>
    </div>
    </form>
</body>
</html>

AllProducts.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindTableAdapters;
public partial class AllProducts : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ProductsTableAdapter productsAdapter = new
         ProductsTableAdapter();
        GridView1.DataSource = productsAdapter.GetProducts();
        GridView1.DataBind();
    }
}

L'elenco dei prodotti viene visualizzato in un controllo GridView

Figura 13: L'elenco dei prodotti viene visualizzato in un controllo GridView (fare clic per visualizzare l'immagine a dimensione intera)

Anche se in questo esempio sono necessarie tre righe di codice nel gestore eventi Page_Load della pagina di ASP.NET , nelle esercitazioni future verrà illustrato come usare ObjectDataSource per recuperare in modo dichiarativo i dati da DAL. Con ObjectDataSource non è necessario scrivere codice e si otterrà anche il supporto per il paging e l'ordinamento.

Passaggio 3: Aggiunta di metodi con parametri al livello di accesso ai dati

A questo punto la classe ProductsTableAdapter ha un metodo, GetProducts(), che restituisce tutti i prodotti nel database. Pur essendo in grado di lavorare con tutti i prodotti è sicuramente utile, ci sono momenti in cui vogliamo recuperare informazioni su un prodotto specifico o tutti i prodotti che appartengono a una determinata categoria. Per aggiungere tali funzionalità al livello di accesso ai dati, è possibile aggiungere metodi con parametri all'oggetto TableAdapter.

Aggiungere ora il metodo GetProductsByCategoryID(categoryID). Per aggiungere un nuovo metodo a DAL, tornare al Designer DataSet, fare clic con il pulsante destro del mouse nella sezione ProductsTableAdapter e scegliere Aggiungi query.

Fare clic con il pulsante destro del mouse su TableAdapter e scegliere Aggiungi query

Figura 14: Right-Click nel TableAdapter e scegliere Aggiungi query

Viene richiesto prima di tutto se si vuole accedere al database usando un'istruzione SQL ad hoc o una stored procedure nuova o esistente. Si sceglierà di usare di nuovo un'istruzione SQL ad hoc. Viene quindi chiesto quale tipo di query SQL si vuole usare. Poiché si desidera restituire tutti i prodotti appartenenti a una categoria specificata, si vuole scrivere un'istruzione SELECT che restituisce righe.

Scegliere di creare un'istruzione SELECT che restituisce righe

Figura 15: Scegliere di creare un'istruzione SELECT che restituisce righe (fare clic per visualizzare l'immagine a dimensione intera)

Il passaggio successivo consiste nel definire la query SQL usata per accedere ai dati. Poiché si desidera restituire solo i prodotti che appartengono a una determinata categoria, si usa la stessa istruzione SELECT da GetProducts(), ma aggiungere la clausola WHERE seguente: WHERE CategoryID = @CategoryID. Il parametro @CategoryID indica alla procedura guidata TableAdapter che il metodo che si sta creando richiederà un parametro di input del tipo corrispondente (vale a dire un numero intero nullable).

Immettere una query per restituire solo i prodotti in una categoria specificata

Figura 16: Immettere una query per restituire solo i prodotti in una categoria specificata (fare clic per visualizzare un'immagine di dimensioni intere)

Nel passaggio finale è possibile scegliere i modelli di accesso ai dati da usare, nonché personalizzare i nomi dei metodi generati. Per il modello Fill, si modificherà il nome in FillByCategoryID e per restituire un modello restituito DataTable (i metodi GetX ), si userà GetProductsByCategoryID.

Scegliere i nomi per i metodi TableAdapter

Figura 17: Scegliere i nomi per i metodi TableAdapter (fare clic per visualizzare l'immagine a dimensione intera)

Al termine della procedura guidata, il Designer DataSet include i nuovi metodi TableAdapter.

I prodotti possono ora essere sottoposti a query per categoria

Figura 18: i prodotti possono ora essere sottoposti a query per categoria

Prendere un momento per aggiungere un metodo GetProductByProductID(productID) usando la stessa tecnica.

Queste query con parametri possono essere testate direttamente dall'Designer DataSet. Fare clic con il pulsante destro del mouse sul metodo in TableAdapter e scegliere Anteprima dati. Immettere quindi i valori da usare per i parametri e fare clic su Anteprima.

Tali prodotti appartenenti alla categoria bevande sono visualizzati

Figura 19: i prodotti appartenenti alla categoria Bevande sono visualizzati (fare clic per visualizzare l'immagine full-size)

Con il metodo GetProductsByCategoryID(categoryID) nel nostro DAL, è ora possibile creare una pagina di ASP.NET che visualizza solo tali prodotti in una categoria specificata. Nell'esempio seguente vengono illustrati tutti i prodotti che si trovano nella categoria Drinks, che hanno un oggetto CategoryID pari a 1.

Beverages.asp

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Beverages.aspx.cs"
    Inherits="Beverages" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h2>Beverages</h2>
        <p>
            <asp:GridView ID="GridView1" runat="server"
             CssClass="DataWebControlStyle">
               <HeaderStyle CssClass="HeaderStyle" />
               <AlternatingRowStyle CssClass="AlternatingRowStyle" />
            </asp:GridView>
             </p>
    </div>
    </form>
</body>
</html>

Beverages.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindTableAdapters;
public partial class Beverages : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ProductsTableAdapter productsAdapter = new
         ProductsTableAdapter();
        GridView1.DataSource =
          productsAdapter.GetProductsByCategoryID(1);
        GridView1.DataBind();
    }
}

Tali prodotti nella categoria Bevande vengono visualizzati

Figura 20: i prodotti nella categoria Bevande vengono visualizzati (fare clic per visualizzare l'immagine a dimensioni complete)

Passaggio 4: Inserimento, aggiornamento ed eliminazione di dati

Esistono due modelli comunemente usati per l'inserimento, l'aggiornamento e l'eliminazione dei dati. Il primo modello, che chiamerò il modello diretto del database, prevede la creazione di metodi che, quando richiamati, generano un comando INSERT, UPDATE o DELETE al database che opera su un singolo record di database. Tali metodi vengono in genere passati in una serie di valori scalari (numeri interi, stringhe, booleani, DateTimes e così via) che corrispondono ai valori da inserire, aggiornare o eliminare. Ad esempio, con questo modello per la tabella Products il metodo delete accetta un parametro integer, che indica l'ID ProductID del record da eliminare, mentre il metodo insert accetta una stringa per ProductName, un decimale per UnitPrice, un intero per UnitsOnStock e così via.

Ogni richiesta di inserimento, aggiornamento ed eliminazione viene inviata immediatamente al database

Figura 21: ogni richiesta di inserimento, aggiornamento ed eliminazione viene inviata immediatamente al database (fare clic per visualizzare l'immagine full-size)

L'altro modello, a cui si fa riferimento come modello di aggiornamento batch, consiste nell'aggiornare un intero DataSet, DataTable o una raccolta di DataRows in una chiamata al metodo. Con questo modello uno sviluppatore elimina, inserisce e modifica i DataRows in una tabella dati e quindi passa tali dataRows o DataTable in un metodo di aggiornamento. Questo metodo enumera quindi i DataRows passati, determina se sono stati modificati, aggiunti o eliminati (tramite il valore della proprietà RowState di DataRow) e genera la richiesta di database appropriata per ogni record.

Tutte le modifiche vengono sincronizzate con il database quando viene richiamato il metodo Update

Figura 22: Tutte le modifiche vengono sincronizzate con il database Quando viene richiamato il metodo di aggiornamento (fare clic per visualizzare l'immagine a dimensioni complete)

TableAdapter usa il modello di aggiornamento batch per impostazione predefinita, ma supporta anche il modello diretto del database. Poiché è stata selezionata l'opzione "Genera istruzioni Insert, Update ed Delete" dalle proprietà avanzate durante la creazione di TableAdapter, ProductsTableAdapter contiene un metodo Update() che implementa il modello di aggiornamento batch. In particolare, TableAdapter contiene un metodo Update() che può essere passato a DataSet tipizzato, a DataTable fortemente tipizzato o a uno o più DataRows. Se si lascia la casella di controllo "GenerateDBDirectMethods" selezionata quando si crea prima tableAdapter il modello diretto del database verrà implementato anche tramite i metodi Insert(), Update()e Delete().

Entrambi i modelli di modifica dei dati usano le proprietà InsertCommand, UpdateCommand e DeleteCommand di TableAdapter per eseguire i comandi INSERT, UPDATE e DELETE nel database. È possibile controllare e modificare le proprietà InsertCommand, UpdateCommand e DeleteCommand facendo clic su TableAdapter nella Designer dataset e quindi passando alla Finestra Proprietà. Assicurarsi di aver selezionato TableAdapter e che l'oggetto ProductsTableAdapter sia quello selezionato nell'elenco a discesa nel Finestra Proprietà.

TableAdapter ha Proprietà InsertCommand, UpdateCommand e DeleteCommand

Figura 23: TableAdapter ha InsertCommand, UpdateCommand e DeleteCommand Properties (Fare clic per visualizzare l'immagine full-size)

Per esaminare o modificare una di queste proprietà dei comandi di database, fare clic sulla sottoproperty CommandText , che verrà visualizzata da Generatore query.

Configurare le istruzioni INSERT, UPDATE e DELETE nel Generatore query

Figura 24: Configurare le istruzioni INSERT, UPDATE e DELETE nel Generatore query (fare clic per visualizzare l'immagine full-size)

Nell'esempio di codice seguente viene illustrato come usare il modello di aggiornamento batch per raddoppiare il prezzo di tutti i prodotti non interrotti e che hanno 25 unità in magazzino o meno:

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
  new NorthwindTableAdapters.ProductsTableAdapter();
// For each product, double its price if it is not discontinued and
// there are 25 items in stock or less
Northwind.ProductsDataTable products = productsAdapter.GetProducts();
foreach (Northwind.ProductsRow product in products)
   if (!product.Discontinued && product.UnitsInStock <= 25)
      product.UnitPrice *= 2;
// Update the products
productsAdapter.Update(products);

Il codice seguente illustra come usare il modello diretto del database per eliminare a livello di codice un determinato prodotto, quindi aggiornare uno e quindi aggiungere uno nuovo:

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
    new NorthwindTableAdapters.ProductsTableAdapter();
// Delete the product with ProductID 3
productsAdapter.Delete(3);
// Update Chai (ProductID of 1), setting the UnitsOnOrder to 15
productsAdapter.Update("Chai", 1, 1, "10 boxes x 20 bags",
  18.0m, 39, 15, 10, false, 1);
// Add a new product
productsAdapter.Insert("New Product", 1, 1,
  "12 tins per carton", 14.95m, 15, 0, 10, false);

Creazione di metodi di inserimento, aggiornamento ed eliminazione personalizzati

I metodi Insert(), Update()e Delete() creati dal metodo diretto del database possono essere un po' complessa, soprattutto per le tabelle con molte colonne. Esaminando l'esempio di codice precedente, senza IntelliSense è utile che non sia particolarmente chiaro quale colonna della tabella Products esegue il mapping a ogni parametro di input ai metodi Update() e Insert(). Potrebbero esserci momenti in cui si vuole aggiornare solo una singola colonna o due oppure si vuole un metodo Insert() personalizzato che restituirà, forse, il valore del campo IDENTITY del record appena inserito (incremento automatico).

Per creare un metodo personalizzato, tornare all'Designer DataSet. Fare clic con il pulsante destro del mouse su TableAdapter e scegliere Aggiungi query, tornare alla procedura guidata TableAdapter. Nella seconda schermata è possibile indicare il tipo di query da creare. Verrà creato un metodo che aggiunge un nuovo prodotto e quindi restituisce il valore del ProductID del record appena aggiunto. Di conseguenza, scegliere di creare una query INSERT .

Creare un metodo per aggiungere una nuova riga alla tabella Prodotti

Figura 25: Creare un metodo per aggiungere una nuova riga alla tabella Prodotti (fare clic per visualizzare l'immagine full-size)

Nella schermata successiva viene visualizzato Il comando InsertCommand'sCommandText . Aumentare questa query aggiungendo SELECT SCOPE_IDENTITY() alla fine della query, che restituirà l'ultimo valore di identità inserito in una colonna IDENTITY nello stesso ambito. Vedere la documentazione tecnica per altre informazioni su SCOPE_IDENTITY() e sul motivo per cui probabilmente si vuole usare SCOPE_IDENTITY() al posto di @@IDENTITY. Assicurarsi di terminare l'istruzione INSERT con un punto e virgola prima di aggiungere l'istruzione SELECT .

Aumentare la query per restituire il valore SCOPE_IDENTITY()

Figura 26: Aumentare la query per restituire il valore SCOPE_IDENTITY() (Fare clic per visualizzare l'immagine a dimensioni complete)

Infine, assegnare un nome al nuovo metodo InsertProduct.

Impostare il nuovo nome del metodo su InsertProduct

Figura 27: Impostare il nuovo nome del metodo su InsertProduct (Fare clic per visualizzare l'immagine full-size)

Quando si torna al dataset Designer si noterà che ProductsTableAdapter contiene un nuovo metodo, InsertProduct. Se questo nuovo metodo non ha un parametro per ogni colonna nella tabella Products , è probabile che venga dimenticata di terminare l'istruzione INSERT con un punto e virgola. Configurare il metodo InsertProduct e assicurarsi di avere un punto e virgola delimitando le istruzioni INSERT e SELECT .

Per impostazione predefinita, i metodi di inserimento rilasciano metodi non query, ovvero restituiscono il numero di righe interessate. Tuttavia, si vuole che il metodo InsertProduct restituisca il valore restituito dalla query, non il numero di righe interessate. A tale scopo, modificare la proprietà ExecuteMode del metodo InsertProduct su Scalar.

Modificare la proprietà ExecuteMode in Scalar

Figura 28: Modificare la proprietà ExecuteMode su Scalar (fare clic per visualizzare l'immagine a dimensioni complete)

Il codice seguente mostra questo nuovo metodo InsertProduct in azione:

NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
    new NorthwindTableAdapters.ProductsTableAdapter();
// Add a new product
int new_productID = Convert.ToInt32(productsAdapter.InsertProduct
    ("New Product", 1, 1, "12 tins per carton", 14.95m, 10, 0, 10, false));
// On second thought, delete the product
productsAdapter.Delete(new_productID);

Passaggio 5: Completamento del livello di accesso ai dati

Si noti che la classe ProductsTableAdapters restituisce i valori CategoryID e SupplierID dalla tabella Products, ma non include la colonna CategoryName dalla tabella Categories o dalla colonna CompanyName dalla tabella Suppliers, anche se queste sono probabilmente le colonne che si desidera visualizzare quando vengono visualizzate le informazioni sul prodotto. È possibile aumentare il metodo iniziale di TableAdapter, GetProducts(), per includere anche i valori di colonna CategoryName e CompanyName, che aggiorneranno la tabella dati fortemente tipizzata per includere anche queste nuove colonne.

Ciò può presentare un problema, tuttavia, come i metodi di TableAdapter per l'inserimento, l'aggiornamento e l'eliminazione dei dati sono basati su questo metodo iniziale. Fortunatamente, i metodi generati automaticamente per l'inserimento, l'aggiornamento e l'eliminazione non sono interessati dalle sottoquerie nella clausola SELECT . Aggiungendo le query alle categorie e ai fornitori come sottoquery , anziché JOIN , si evita di dover rielaborare tali metodi per modificare i dati. Fare clic con il pulsante destro del mouse sul metodo GetProducts() in ProductsTableAdapter e scegliere Configura. Modificare quindi la clausola SELECT in modo che sia simile al seguente:

SELECT     ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
(SELECT CategoryName FROM Categories
WHERE Categories.CategoryID = Products.CategoryID) as CategoryName,
(SELECT CompanyName FROM Suppliers
WHERE Suppliers.SupplierID = Products.SupplierID) as SupplierName
FROM         Products

Aggiornare l'istruzione SELECT per il metodo GetProducts()

Figura 29: Aggiornare l'istruzione SELECT per il metodo GetProducts() (Fare clic per visualizzare l'immagine full-size)

Dopo aver aggiornato il metodo GetProducts() per usare questa nuova query, DataTable includerà due nuove colonne: CategoryName e SupplierName.

DataTable products include due nuove colonne

Figura 30: La tabella Dei prodotti ha due nuove colonne

È necessario aggiornare anche la clausola SELECT nel metodo GetProductsByCategoryID(categoryID).

Se si aggiorna la sintassiGetProducts()SELECT usando la sintassi JOIN, dataset Designer non sarà in grado di generare automaticamente i metodi per l'inserimento, l'aggiornamento e l'eliminazione dei dati del database usando il modello diretto del database. Sarà invece necessario crearli manualmente come abbiamo fatto con il metodo InsertProduct in precedenza in questa esercitazione. Inoltre, è necessario specificare manualmente i valori delle proprietà InsertCommand, UpdateCommand e DeleteCommand se si vuole usare il modello di aggiornamento batch.

Aggiunta di TableAdapter rimanenti

Fino a questo momento, è stato esaminato solo l'uso di un singolo TableAdapter per una singola tabella di database. Tuttavia, il database Northwind contiene diverse tabelle correlate che sarà necessario usare nell'applicazione Web. Un DataSet tipizzato può contenere più tabelle dati correlate. Di conseguenza, per completare il servizio di gestione dati, è necessario aggiungere DataTables per le altre tabelle che verranno usati in queste esercitazioni. Per aggiungere un nuovo TableAdapter a un DataSet tipizzato, aprire l'Designer DataSet, fare clic con il pulsante destro del mouse sul Designer e scegliere Aggiungi/TableAdapter. Verrà creato un nuovo DataTable e TableAdapter e si esaminerà la procedura guidata esaminata in precedenza in questa esercitazione.

Eseguire alcuni minuti per creare i metodi e tableadapter seguenti usando le query seguenti. Si noti che le query in ProductsTableAdapter includono le sottoquerie per acquisire i nomi di categoria e fornitore di ogni prodotto. Inoltre, se si è già seguito, sono già stati aggiunti i metodi GetProducts() della classe ProductsTableAdapter e GetProductsByCategoryID(categoryID).

  • ProductsTableAdapter

    • GetProducts:

      SELECT     ProductID, ProductName, SupplierID, 
      CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, 
      UnitsOnOrder, ReorderLevel, Discontinued, 
      (SELECT CategoryName FROM Categories WHERE
      Categories.CategoryID = Products.CategoryID) as 
      CategoryName, (SELECT CompanyName FROM Suppliers
      WHERE Suppliers.SupplierID = Products.SupplierID) 
      as SupplierName
      FROM         Products
      
    • GetProductsByCategoryID:

      SELECT     ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued, (SELECT CategoryName
      FROM Categories WHERE Categories.CategoryID = 
      Products.CategoryID) as CategoryName,
      (SELECT CompanyName FROM Suppliers WHERE
      Suppliers.SupplierID = Products.SupplierID)
      as SupplierName
      FROM         Products
      WHERE      CategoryID = @CategoryID
      
    • GetProductsBySupplierID:

      SELECT     ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued, (SELECT CategoryName
      FROM Categories WHERE Categories.CategoryID = 
      Products.CategoryID) as CategoryName, 
      (SELECT CompanyName FROM Suppliers WHERE 
      Suppliers.SupplierID = Products.SupplierID) as SupplierName
      FROM         Products
      WHERE SupplierID = @SupplierID
      
    • GetProductByProductID:

      SELECT     ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued, (SELECT CategoryName 
      FROM Categories WHERE Categories.CategoryID = 
      Products.CategoryID) as CategoryName, 
      (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) 
      as SupplierName
      FROM         Products
      WHERE ProductID = @ProductID
      
  • CategoriesTableAdapter

    • GetCategories:

      SELECT     CategoryID, CategoryName, Description
      FROM         Categories
      
    • GetCategoryByCategoryID:

      SELECT     CategoryID, CategoryName, Description
      FROM         Categories
      WHERE CategoryID = @CategoryID
      
  • SuppliersTableAdapter

    • GetSuppliers:

      SELECT     SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM         Suppliers
      
    • GetSuppliersByCountry:

      SELECT     SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM         Suppliers
      WHERE Country = @Country
      
    • GetSupplierBySupplierID:

      SELECT     SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM         Suppliers
      WHERE SupplierID = @SupplierID
      
  • EmployeesTableAdapter

    • GetEmployees:

      SELECT     EmployeeID, LastName, FirstName, Title,
      HireDate, ReportsTo, Country
      FROM         Employees
      
    • GetEmployeesByManager:

      SELECT     EmployeeID, LastName, FirstName, Title, 
      HireDate, ReportsTo, Country
      FROM         Employees
      WHERE ReportsTo = @ManagerID
      
    • GetEmployeeByEmployeEID:

      SELECT     EmployeeID, LastName, FirstName, Title,
      HireDate, ReportsTo, Country
      FROM         Employees
      WHERE EmployeeID = @EmployeeID
      

DataSet Designer dopo l'aggiunta dei quattro tableAdapter

Figura 31: DataSet Designer dopo l'aggiunta dei quattro tableAdapter (fare clic per visualizzare l'immagine full-size)

Aggiunta di codice personalizzato a DAL

Gli elementi TableAdapters e DataTable aggiunti al DataSet tipizzato vengono espressi come file di definizione xml Schema (Northwind.xsd). È possibile visualizzare queste informazioni sullo schema facendo clic con il pulsante destro del mouse sul file Northwind.xsd nel Esplora soluzioni e scegliendo Visualizza codice.

File XSD (XML Schema Definition) per Northwinds Typed DataSet

Figura 32: File XSD (XML Schema Definition) per Northwinds Typed DataSet (Fare clic per visualizzare l'immagine full-size)

Queste informazioni sullo schema vengono tradotte in codice C# o Visual Basic in fase di progettazione in fase di compilazione o in fase di esecuzione (se necessario), a questo punto è possibile eseguirlo con il debugger. Per visualizzare questo codice generato automaticamente, passare alla visualizzazione classi ed eseguire il drill-down alle classi TableAdapter o Typed DataSet. Se non viene visualizzata la visualizzazione classi sullo schermo, passare al menu Visualizza e selezionarla da lì oppure premere CTRL+MAIUSC+C. Nella visualizzazione classi è possibile visualizzare le proprietà, i metodi e gli eventi delle classi Typed DataSet e TableAdapter. Per visualizzare il codice per un metodo specifico, fare doppio clic sul nome del metodo nella visualizzazione classi o fare clic con il pulsante destro del mouse su di esso e scegliere Vai a definizione.

Esaminare il codice generato automaticamente selezionando Vai a definizione dalla visualizzazione classe

Figura 33: Controllare il codice generato automaticamente selezionando Vai a definizione dalla visualizzazione classi

Anche se il codice generato automaticamente può essere un ottimo risparmio di tempo, il codice è spesso molto generico e deve essere personalizzato per soddisfare le esigenze univoce di un'applicazione. Il rischio di estendere il codice generato automaticamente, tuttavia, è che lo strumento che ha generato il codice potrebbe decidere che è il momento di "rigenerare" e sovrascrivere le personalizzazioni. Con il nuovo concetto di classe parziale di .NET 2.0, è facile suddividere una classe tra più file. Ciò consente di aggiungere metodi, proprietà ed eventi alle classi generate automaticamente senza dover preoccuparsi della sovrascrittura delle personalizzazioni di Visual Studio.

Per illustrare come personalizzare il DAL, aggiungere un metodo GetProducts() alla classe SuppliersRow . La classe SuppliersRow rappresenta un singolo record nella tabella Suppliers ; ogni fornitore può fornire zero a molti prodotti, quindi GetProducts() restituirà tali prodotti del fornitore specificato. Per eseguire questa operazione, creare un nuovo file di classe nella cartella App_Code denominata SuppliersRow.cs e aggiungere il codice seguente:

using System;
using System.Data;
using NorthwindTableAdapters;
public partial class Northwind
{
    public partial class SuppliersRow
    {
        public Northwind.ProductsDataTable GetProducts()
        {
            ProductsTableAdapter productsAdapter =
             new ProductsTableAdapter();
            return
              productsAdapter.GetProductsBySupplierID(this.SupplierID);
        }
    }
}

Questa classe parziale indica al compilatore che quando si compila la classe Northwind.SuppliersRow per includere il metodo GetProducts() appena definito. Se si compila il progetto e si torna alla visualizzazione classi, verrà visualizzato GetProducts() elencato come metodo northwind.SuppliersRow.

Il metodo GetProducts() fa ora parte della classe Northwind.SuppliersRow

Figura 34: Il metodo GetProducts() fa ora parte della classe Northwind.SuppliersRow

Il metodo GetProducts() può ora essere usato per enumerare il set di prodotti per un determinato fornitore, come illustrato nel codice seguente:

NorthwindTableAdapters.SuppliersTableAdapter suppliersAdapter =
    new NorthwindTableAdapters.SuppliersTableAdapter();
// Get all of the suppliers
Northwind.SuppliersDataTable suppliers =
  suppliersAdapter.GetSuppliers();
// Enumerate the suppliers
foreach (Northwind.SuppliersRow supplier in suppliers)
{
    Response.Write("Supplier: " + supplier.CompanyName);
    Response.Write("<ul>");
    // List the products for this supplier
    Northwind.ProductsDataTable products = supplier.GetProducts();
    foreach (Northwind.ProductsRow product in products)
        Response.Write("<li>" + product.ProductName + "</li>");
    Response.Write("</ul><p> </p>");
}

Questi dati possono essere visualizzati anche in uno qualsiasi di ASP. Controlli Web dati di NET. La pagina seguente usa un controllo GridView con due campi:

  • Oggetto BoundField che visualizza il nome di ogni fornitore e
  • ModelloField che contiene un controllo BulletedList associato ai risultati restituiti dal metodo GetProducts() per ogni fornitore.

Verranno esaminati come visualizzare tali report master-dettagli nelle esercitazioni future. Per il momento, questo esempio è progettato per illustrare l'uso del metodo personalizzato aggiunto alla classe Northwind.SuppliersRow .

SuppliersAndProducts.aspx

<%@ Page Language="C#" CodeFile="SuppliersAndProducts.aspx.cs"
    AutoEventWireup="true" Inherits="SuppliersAndProducts" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h2>
            Suppliers and Their Products</h2>
        <p>
            <asp:GridView ID="GridView1" runat="server"
             AutoGenerateColumns="False"
             CssClass="DataWebControlStyle">
                <HeaderStyle CssClass="HeaderStyle" />
                <AlternatingRowStyle CssClass="AlternatingRowStyle" />
                <Columns>
                    <asp:BoundField DataField="CompanyName"
                      HeaderText="Supplier" />
                    <asp:TemplateField HeaderText="Products">
                        <ItemTemplate>
                            <asp:BulletedList ID="BulletedList1"
                             runat="server" DataSource="<%# ((Northwind.SuppliersRow) ((System.Data.DataRowView) Container.DataItem).Row).GetProducts() %>"
                                 DataTextField="ProductName">
                            </asp:BulletedList>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
             </p>
    </div>
    </form>
</body>
</html>

SuppliersAndProducts.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindTableAdapters;
public partial class SuppliersAndProducts : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        SuppliersTableAdapter suppliersAdapter = new
          SuppliersTableAdapter();
        GridView1.DataSource = suppliersAdapter.GetSuppliers();
        GridView1.DataBind();
    }
}

Il nome della società del fornitore è elencato nella colonna sinistra, i loro prodotti a destra

Figura 35: Il nome della società del fornitore è elencato nella colonna a sinistra, i loro prodotti a destra (fare clic per visualizzare l'immagine a dimensioni complete)

Riepilogo

Quando si crea un'applicazione Web che crea il servizio dal servizio dati deve essere uno dei primi passaggi, prima di iniziare a creare il livello di presentazione. Con Visual Studio, la creazione di un DAL basato su DataSet tipizzato è un'attività che può essere eseguita in 10-15 minuti senza scrivere una riga di codice. Le esercitazioni che si spostano avanti creeranno su questo DAL. Nell'esercitazione successiva verrà definito un numero di regole business e verrà illustrato come implementarli in un livello di logica di business separato.

Programmazione felice!

Altre informazioni

Per altre informazioni sugli argomenti illustrati in questa esercitazione, vedere le risorse seguenti:

Training video sugli argomenti contenuti in questa esercitazione

Informazioni sull'autore

Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Microsoft Web dal 1998. Scott lavora come consulente indipendente, allenatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2,0 in 24 Ore. Può essere raggiunto a mitchell@4GuysFromRolla.com. o tramite il suo blog, che può essere trovato in http://ScottOnWriting.NET.

Grazie speciali

Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali per questa esercitazione sono stati Ron Green, Hilton Giesenow, Dennis Patterson, Liz Shulok, Abel Gomez e Carlos Santos. Interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com.