Condividi tramite


Aggiornamento del TableAdapter per l'uso dei join (C#)

di Scott Mitchell

Scarica il PDF

Quando si usa un database, è comune richiedere dati distribuiti tra più tabelle. Per recuperare dati da due tabelle diverse, è possibile usare una sottoquery correlata o un'operazione JOIN. In questa esercitazione vengono confrontate le sottoquery correlate e la sintassi JOIN prima di esaminare come creare un TableAdapter che include un JOIN nella query principale.

Introduzione

Con i database relazionali, i dati con cui si è interessati sono spesso distribuiti in più tabelle. Ad esempio, quando vengono visualizzate informazioni sul prodotto, è probabile che si voglia elencare ogni prodotto corrispondente categoria e nomi dei fornitori. La Products tabella ha CategoryID valori e SupplierID , ma i nomi di categoria e fornitori effettivi si trovano rispettivamente nelle Categories tabelle e Suppliers .

Per recuperare informazioni da un'altra tabella correlata, è possibile usare sottoquery correlate o JOINs. Una sottoquery correlata è una query nidificata SELECT che fa riferimento a colonne nella query esterna. Ad esempio, nell'esercitazione Creazione di un livello di accesso ai dati sono stati usati due sottoquery correlate nella ProductsTableAdapter query principale della query principale per restituire la categoria e i nomi dei fornitori per ogni prodotto. È JOIN un costrutto SQL che unisce righe correlate da due tabelle diverse. È stato usato un JOIN oggetto nell'esercitazione Esecuzione di query sui dati con il controllo SqlDataSource per visualizzare le informazioni sulle categorie insieme a ogni prodotto.

Il motivo per cui si è astenuto dall'uso JOIN di s con gli oggetti TableAdapter è dovuto alle limitazioni della procedura guidata di TableAdapter per generare automaticamente istruzioni , UPDATEe DELETE corrispondentiINSERT. In particolare, se la query principale di TableAdapter contiene oggetti JOIN , TableAdapter non può creare automaticamente le istruzioni SQL ad hoc o le stored procedure per InsertCommandle relative proprietà , UpdateCommande DeleteCommand .

In questa esercitazione verranno confrontate brevemente e contrastate sottoquery correlate e JOIN s prima di esplorare come creare un TableAdapter che include JOIN s nella query principale.

Confronto e contrasto di sottoquery eJOIN s correlate

Tenere presente che l'oggetto ProductsTableAdapter creato nella prima esercitazione in Northwind DataSet usa sottoquery correlate per riportare ogni prodotto corrispondente categoria e nome fornitore. La ProductsTableAdapter query principale è illustrata di seguito.

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

Le due sottoquery correlate, (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID) e , sono SELECT query che restituiscono un singolo valore per prodotto come colonna aggiuntiva nell'elenco di colonne dell'istruzione esterna SELECT(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) .

In alternativa, è possibile utilizzare un oggetto JOIN per restituire ogni fornitore e nome di categoria del prodotto. La query seguente restituisce lo stesso output di quello precedente, ma usa JOIN s al posto delle sottoquery:

SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       Categories.CategoryName, 
       Suppliers.CompanyName as SupplierName
FROM Products
    LEFT JOIN Categories ON
        Categories.CategoryID = Products.CategoryID
    LEFT JOIN Suppliers ON
        Suppliers.SupplierID = Products.SupplierID

Un JOIN oggetto unisce i record di una tabella con i record di un'altra tabella in base ad alcuni criteri. Nella query precedente, ad esempio, LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID indica SQL Server di unire ogni record di prodotto con il record di categoria il cui CategoryID valore corrisponde al valore del CategoryID prodotto. Il risultato unito consente di usare i campi di categoria corrispondenti per ogni prodotto ( ad esempio CategoryName).

Nota

JOIN s viene comunemente usato durante l'esecuzione di query sui dati dai database relazionali. Se non si ha più a che fare con la JOIN sintassi o se è necessario spolverare un po' sull'utilizzo, è consigliabile usare l'esercitazione per l'aggiunta a SQL in W3 Schools. Vale anche la pena leggere le JOIN sezioni Nozioni fondamentali e Nozioni fondamentali della sottoquery della documentazione online di SQL.

Poiché JOIN le sottoquery s e correlate possono essere usate entrambe per recuperare i dati correlati da altre tabelle, molti sviluppatori si mettono a graffiare le teste e chiedersi quale approccio usare. Tutti i guru SQL che ho parlato hanno detto approssimativamente la stessa cosa, che non importa davvero le prestazioni, come SQL Server produrrà piani di esecuzione approssimativamente identici. Il loro consiglio, quindi, è quello di usare la tecnica con cui l'utente e il team sono più comodi. Merita di notare che, dopo aver impartito questo consiglio, questi esperti esprimono immediatamente la loro preferenza per JOIN le sottoquery correlate.

Quando si compila un livello di accesso ai dati usando set di dati tipiti, gli strumenti funzionano meglio quando si usano sottoquery. In particolare, la procedura guidata di TableAdapter non genererà automaticamente istruzioni , UPDATEe DELETE corrispondenti INSERTse la query principale contiene sJOIN, ma genererà automaticamente queste istruzioni quando vengono usate sottoquery correlate.

Per esplorare questo problema, creare un dataset tipizzato temporaneo nella ~/App_Code/DAL cartella . Durante la Configurazione guidata TableAdapter, scegliere di usare istruzioni SQL ad hoc e immettere la query seguente SELECT (vedere la figura 1):

SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       Categories.CategoryName, 
       Suppliers.CompanyName as SupplierName
FROM Products
    LEFT JOIN Categories ON
        Categories.CategoryID = Products.CategoryID
    LEFT JOIN Suppliers ON
        Suppliers.SupplierID = Products.SupplierID

Screenshot che mostra la finestra Configurazione guidata TableAdaptor con una query immessa che contiene JOIN.

Figura 1: Immettere una query principale che contiene JOIN (fare clic per visualizzare l'immagine a dimensione intera)

Per impostazione predefinita, TableAdapter creerà INSERTautomaticamente istruzioni , UPDATEe DELETE in base alla query principale. Se si fa clic sul pulsante Avanzate, si noterà che questa funzionalità è abilitata. Nonostante questa impostazione, TableAdapter non sarà in grado di creare le INSERTistruzioni , UPDATEe DELETE perché la query principale contiene un oggetto JOIN.

Screenshot che mostra la finestra Opzioni avanzate con la casella di controllo Genera istruzioni Inserisci, Aggiorna ed Elimina selezionata.

Figura 2: Immettere una query principale che contiene JOIN s

Fare clic su Fine per completare la procedura guidata. A questo punto l'Designer di DataSet includerà un singolo Oggetto TableAdapter con una tabella DataTable con colonne per ognuno dei campi restituiti nell'elenco SELECT di colonne della query. Sono inclusi e CategoryNameSupplierName, come illustrato nella figura 3.

DataTable include una colonna per ogni campo restituito nell'elenco colonne

Figura 3: DataTable include una colonna per ogni campo restituito nell'elenco colonne

Mentre DataTable include le colonne appropriate, TableAdapter non dispone di valori per InsertCommandle relative proprietà , UpdateCommande DeleteCommand . Per confermarlo, fare clic su TableAdapter nel Designer e quindi passare alla Finestra Proprietà. Si noterà che le InsertCommandproprietà , UpdateCommande DeleteCommand sono impostate su (Nessuno).

Le proprietà InsertCommand, UpdateCommand e DeleteCommand sono impostate su (Nessuna)

Figura 4: Le InsertCommandproprietà , UpdateCommande DeleteCommand sono impostate su (Nessuna) (Fare clic per visualizzare l'immagine a dimensione intera)

Per risolvere questo problema, è possibile fornire manualmente le istruzioni SQL e i parametri per le InsertCommandproprietà , UpdateCommande DeleteCommand tramite il Finestra Proprietà. In alternativa, è possibile iniziare configurando la query principale dell'oggetto TableAdapter in modo da non includere elementi JOIN . In questo modo le INSERTistruzioni , UPDATEe DELETE verranno generate automaticamente. Dopo aver completato la procedura guidata, è possibile aggiornare manualmente l'oggetto TableAdapter dal SelectCommand Finestra Proprietà in modo che includa la JOIN sintassi.

Anche se questo approccio funziona, è molto fragile quando si usano query SQL ad hoc perché ogni volta che la query principale di TableAdapter viene riconfigurata tramite la procedura guidata, le istruzioni , UPDATEe DELETE generate INSERTautomaticamente vengono ricreate. Ciò significa che tutte le personalizzazioni apportate in un secondo momento andrebbero perse se si fa clic con il pulsante destro del mouse su TableAdapter, si sceglie Configura dal menu di scelta rapida e si completa nuovamente la procedura guidata.

La fragilità delle istruzioni , UPDATEe DELETE generate INSERTautomaticamente di TableAdapter è, fortunatamente, limitata alle istruzioni SQL ad hoc. Se tableAdapter usa stored procedure, è possibile personalizzare le SelectCommandstored procedure , InsertCommand, UpdateCommando DeleteCommand ed eseguire di nuovo la Configurazione guidata TableAdapter senza dover temere che le stored procedure vengano modificate.

Nei passaggi successivi verrà creato un TableAdapter che, inizialmente, usa una query principale che omette qualsiasi JOIN s in modo che le stored procedure di inserimento, aggiornamento ed eliminazione corrispondenti vengano generate automaticamente. Verrà quindi aggiornato in SelectCommand modo che usi un JOIN oggetto che restituisce colonne aggiuntive da tabelle correlate. Infine, verrà creata una classe Livello logica di business corrispondente e verrà illustrato l'uso di TableAdapter in una pagina Web ASP.NET.

Passaggio 1: Creazione dell'oggetto TableAdapter tramite una query principale semplificata

Per questa esercitazione si aggiungeranno un oggetto TableAdapter e dataTable fortemente tipizzato per la Employees tabella in NorthwindWithSprocs DataSet. La Employees tabella contiene un ReportsTo campo che ha specificato l'oggetto EmployeeID del responsabile del dipendente. Ad esempio, il dipendente Anne Dodsworth ha un ReportTo valore pari a 5, ovvero quello EmployeeID di Steven Buchanan. Di conseguenza, Anne riferisce a Steven, il suo manager. Oltre a segnalare il valore di ReportsTo ogni dipendente, è anche possibile recuperare il nome del responsabile. Questa operazione può essere eseguita usando un oggetto JOIN. Tuttavia, l'uso di un oggetto JOIN quando si crea inizialmente TableAdapter impedisce alla procedura guidata di generare automaticamente le funzionalità di inserimento, aggiornamento ed eliminazione corrispondenti. Si inizierà quindi creando un TableAdapter la cui query principale non contiene elementi JOIN . Quindi, nel passaggio 2, si aggiornerà la stored procedure di query principale per recuperare il nome del gestore tramite un .JOIN

Per iniziare, aprire l'oggetto NorthwindWithSprocs DataSet nella ~/App_Code/DAL cartella . Fare clic con il pulsante destro del mouse sulla Designer, scegliere l'opzione Aggiungi dal menu di scelta rapida e scegliere la voce di menu TableAdapter. Verrà avviata la Configurazione guidata TableAdapter. Come illustrato nella figura 5, creare nuove stored procedure nella procedura guidata e fare clic su Avanti. Per un aggiornamento sulla creazione di nuove stored procedure dalla creazione guidata di TableAdapter, vedere l'esercitazione Creazione di nuove stored procedure per l'esercitazione TableAdapters di DataSet tipizzato .

Selezionare l'opzione Crea nuove stored procedure

Figura 5: Selezionare l'opzione Crea nuove stored procedure (fare clic per visualizzare l'immagine a dimensione intera)

Usare l'istruzione seguente SELECT per la query principale di TableAdapter:

SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees

Poiché questa query non include elementiJOIN, la Creazione guidata TableAdapter creerà automaticamente stored procedure con istruzioni , UPDATEe DELETE corrispondentiINSERT, nonché una stored procedure per l'esecuzione della query principale.

Il passaggio seguente consente di denominare le stored procedure di TableAdapter. Usare i nomi Employees_Select, Employees_Insert, Employees_Updatee Employees_Delete, come illustrato nella figura 6.

Denominare le stored procedure tableadapter

Figura 6: Assegnare un nome alle stored procedure di TableAdapter (fare clic per visualizzare l'immagine a dimensione intera)

Il passaggio finale richiede di denominare i metodi di TableAdapter. Usare Fill e GetEmployees come nomi di metodo. Assicurarsi anche di lasciare selezionata la casella di controllo Crea metodi per inviare gli aggiornamenti direttamente al database (GenerateDBDirectMethods).

Denominare i metodi tableAdapter Fill e GetEmployees

Figura 7: Denominare i metodi Fill di TableAdapter e GetEmployees (fare clic per visualizzare l'immagine a dimensione intera)

Al termine della procedura guidata, esaminare le stored procedure nel database. Dovrebbero essere visualizzati quattro nuovi: Employees_Select, Employees_Insert, Employees_Updatee Employees_Delete. Esaminare quindi e EmployeesDataTableEmployeesTableAdapter appena creato. La tabella DataTable contiene una colonna per ogni campo restituito dalla query principale. Fare clic su TableAdapter e quindi passare alla Finestra Proprietà. Si noterà che le InsertCommandproprietà , UpdateCommande DeleteCommand sono configurate correttamente per chiamare le stored procedure corrispondenti.

TableAdapter include funzionalità di inserimento, aggiornamento ed eliminazione

Figura 8: TableAdapter include funzionalità di inserimento, aggiornamento ed eliminazione (fare clic per visualizzare l'immagine a dimensione intera)

Con le stored procedure di inserimento, aggiornamento ed eliminazione create automaticamente e le InsertCommandproprietà , UpdateCommande DeleteCommand configurate correttamente, è possibile personalizzare la SelectCommand stored procedure per restituire informazioni aggiuntive su ogni responsabile del dipendente. In particolare, è necessario aggiornare la Employees_Select stored procedure per usare e JOIN restituire i valori e LastName del FirstName gestore. Dopo aver aggiornato la stored procedure, sarà necessario aggiornare DataTable in modo che includa queste colonne aggiuntive. Queste due attività verranno affrontate nei passaggi 2 e 3.

Passaggio 2: Personalizzazione della stored procedure per includere unJOIN

Per iniziare, passare a Esplora server, eseguire il drill-down nella cartella Stored procedure del database Northwind e aprire la Employees_Select stored procedure. Se questa stored procedure non viene visualizzata, fare clic con il pulsante destro del mouse sulla cartella Stored procedure e scegliere Aggiorna. Aggiornare la stored procedure in modo che usi un LEFT JOIN oggetto per restituire il nome e il cognome del manager:

SELECT Employees.EmployeeID, Employees.LastName, 
       Employees.FirstName, Employees.Title, 
       Employees.HireDate, Employees.ReportsTo, 
       Employees.Country,
       Manager.FirstName as ManagerFirstName, 
       Manager.LastName as ManagerLastName
FROM Employees
    LEFT JOIN Employees AS Manager ON
        Employees.ReportsTo = Manager.EmployeeID

Dopo aver aggiornato l'istruzione SELECT , salvare le modifiche passando al menu File e scegliendo Salva Employees_Select. In alternativa, è possibile fare clic sull'icona Salva sulla barra degli strumenti o premere CTRL+S. Dopo aver salvato le modifiche, fare clic con il pulsante destro del Employees_Select mouse sulla stored procedure in Esplora server e scegliere Esegui. Verrà eseguita la stored procedure e verranno visualizzati i risultati nella finestra Output (vedere la figura 9).

I risultati delle stored procedure vengono visualizzati nella finestra di output

Figura 9: I risultati delle stored procedure vengono visualizzati nella finestra di output (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 3: Aggiornamento delle colonne di DataTable

A questo punto, la Employees_Select stored procedure restituisce ManagerFirstName i valori e ManagerLastName , ma manca EmployeesDataTable queste colonne. Queste colonne mancanti possono essere aggiunte a DataTable in uno dei due modi seguenti:

  • Manualmente: fare clic con il pulsante destro del mouse su DataTable nel Designer DataSet e scegliere Colonna dal menu Aggiungi. È quindi possibile denominare la colonna e impostarne le proprietà di conseguenza.
  • Automaticamente : la Configurazione guidata TableAdapter aggiornerà le colonne di DataTable in modo da riflettere i campi restituiti dalla SelectCommand stored procedure. Quando si usano istruzioni SQL ad hoc, la procedura guidata rimuoverà anche le InsertCommandproprietà , UpdateCommande DeleteCommand poiché ora SelectCommand contiene un oggetto JOIN. Tuttavia, quando si usano stored procedure, queste proprietà del comando rimangono intatte.

È stata esaminata l'aggiunta manuale di colonne DataTable nelle esercitazioni precedenti, tra cui Master/Detail Using a Bulleted List of Master Records with a Details DataList and Uploading Files (Elenco puntato di record master con un oggetto Details DataList e caricamento di file) e questo processo verrà esaminato di nuovo in modo più dettagliato nell'esercitazione successiva. Per questa esercitazione, tuttavia, è possibile usare l'approccio automatico tramite la Configurazione guidata TableAdapter.

Per iniziare, fare clic con il pulsante destro del EmployeesTableAdapter mouse su e scegliere Configura dal menu di scelta rapida. Verrà visualizzata la Configurazione guidata TableAdapter, che elenca le stored procedure usate per la selezione, l'inserimento, l'aggiornamento e l'eliminazione, insieme ai valori restituiti e ai parametri (se presenti). La figura 10 mostra questa procedura guidata. Qui è possibile osservare che la Employees_Select stored procedure restituisce ora i ManagerFirstName campi e ManagerLastName .

La procedura guidata mostra l'elenco di colonne aggiornato per la stored procedure Employees_Select

Figura 10: La procedura guidata mostra l'elenco di colonne aggiornato per la Employees_Select stored procedure (fare clic per visualizzare l'immagine a dimensione intera)

Completare la procedura guidata facendo clic su Fine. Al ritorno al Designer DataSet, include EmployeesDataTable due colonne aggiuntive: ManagerFirstName e ManagerLastName.

EmployeesDataTable contiene due nuove colonne

Figura 11: EmployeesDataTable Contiene due nuove colonne (fare clic per visualizzare l'immagine a dimensione intera)

Per illustrare che la stored procedure aggiornata Employees_Select è attiva e che le funzionalità di inserimento, aggiornamento ed eliminazione di TableAdapter sono ancora funzionanti, è possibile creare una pagina Web che consente agli utenti di visualizzare ed eliminare i dipendenti. Prima di creare una pagina di questo tipo, tuttavia, è necessario creare una nuova classe nel livello della logica di business per lavorare con i dipendenti di NorthwindWithSprocs DataSet. Nel passaggio 4 verrà creata una EmployeesBLLWithSprocs classe. Nel passaggio 5 questa classe verrà usata da una pagina ASP.NET.

Passaggio 4: Implementazione del livello della logica di business

Creare un nuovo file di classe nella ~/App_Code/BLL cartella denominata EmployeesBLLWithSprocs.cs. Questa classe simula la semantica della classe esistente EmployeesBLL , solo questa nuova fornisce un minor numero di metodi e usa l'oggetto NorthwindWithSprocs DataSet anziché l'oggetto Northwind DataSet. Aggiungere il codice seguente alla classe EmployeesBLLWithSprocs .

using System;
using System.Data;
using System.Configuration;
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 NorthwindWithSprocsTableAdapters;
[System.ComponentModel.DataObject]
public class EmployeesBLLWithSprocs
{
    private EmployeesTableAdapter _employeesAdapter = null;
    protected EmployeesTableAdapter Adapter
    {
        get
        {
            if (_employeesAdapter == null)
                _employeesAdapter = new EmployeesTableAdapter();
            return _employeesAdapter;
        }
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, true)]
    public NorthwindWithSprocs.EmployeesDataTable GetEmployees()
    {
        return Adapter.GetEmployees();
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Delete, true)]
    public bool DeleteEmployee(int employeeID)
    {
        int rowsAffected = Adapter.Delete(employeeID);
        // Return true if precisely one row was deleted, otherwise false
        return rowsAffected == 1;
    }
}

La EmployeesBLLWithSprocs proprietà della Adapter classe restituisce un'istanza dell'oggetto NorthwindWithSprocs DataSet s EmployeesTableAdapter. Viene usato dai metodi e DeleteEmployee della classe GetEmployees . Il GetEmployees metodo chiama il EmployeesTableAdapter metodo corrispondente GetEmployees , che richiama la Employees_Select stored procedure e popola i risultati in un oggetto EmployeeDataTable. Il DeleteEmployee metodo chiama in modo analogo il EmployeesTableAdapter metodo s Delete , che richiama la Employees_Delete stored procedure.

Passaggio 5: Utilizzo dei dati nel livello presentazione

Al termine della EmployeesBLLWithSprocs classe, è possibile lavorare con i dati dei dipendenti tramite una pagina di ASP.NET. Aprire la JOINs.aspx pagina nella AdvancedDAL cartella e trascinare gridView dalla casella degli strumenti nella Designer, impostandone la ID proprietà su Employees. Successivamente, dallo smart tag di GridView associare la griglia a un nuovo controllo ObjectDataSource denominato EmployeesDataSource.

Configurare ObjectDataSource per l'uso della EmployeesBLLWithSprocs classe e, dalle schede SELECT e DELETE, assicurarsi che i GetEmployees metodi e DeleteEmployee siano selezionati dagli elenchi a discesa. Fare clic su Fine per completare la configurazione di ObjectDataSource.

Configurare ObjectDataSource per l'uso della classe EmployeesBLLWithSprocs

Figura 12: Configurare ObjectDataSource per l'uso della classe (fare clic per visualizzare l'immagineEmployeesBLLWithSprocs a dimensione intera)

Fare in modo che ObjectDataSource usi i metodi GetEmployees e DeleteEmployee

Figura 13: Usare ObjectDataSource metodi GetEmployees e DeleteEmployee (fare clic per visualizzare l'immagine a dimensione intera)

Visual Studio aggiungerà un BoundField a GridView per ognuna delle EmployeesDataTable colonne. Rimuovere tutti questi BoundFields ad eccezione Titledi , LastName, FirstName, ManagerFirstNamee e ManagerLastName rinominare le proprietà per gli HeaderText ultimi quattro BoundFields in Cognome, Nome, Nome, Nome e Cognome del Manager rispettivamente.

Per consentire agli utenti di eliminare i dipendenti da questa pagina, è necessario eseguire due operazioni. In primo luogo, indicare a GridView di fornire funzionalità di eliminazione selezionando l'opzione Abilita eliminazione dallo smart tag. In secondo luogo, modificare la proprietà ObjectDataSource s OldValuesParameterFormatString dal valore impostato dalla procedura guidata ObjectDataSource () al valore predefinito (original_{0}{0}). Dopo aver apportato queste modifiche, il markup dichiarativo di GridView e ObjectDataSource dovrebbe essere simile al seguente:

<asp:GridView ID="Employees" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="EmployeeID" DataSourceID="EmployeesDataSource">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="Title" 
            HeaderText="Title" 
            SortExpression="Title" />
        <asp:BoundField DataField="LastName" 
            HeaderText="Last Name" 
            SortExpression="LastName" />
        <asp:BoundField DataField="FirstName" 
            HeaderText="First Name" 
            SortExpression="FirstName" />
        <asp:BoundField DataField="ManagerFirstName" 
            HeaderText="Manager's First Name" 
            SortExpression="ManagerFirstName" />
        <asp:BoundField DataField="ManagerLastName" 
            HeaderText="Manager's Last Name" 
            SortExpression="ManagerLastName" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="EmployeesDataSource" runat="server" 
    DeleteMethod="DeleteEmployee" OldValuesParameterFormatString="{0}" 
    SelectMethod="GetEmployees" TypeName="EmployeesBLLWithSprocs">
    <DeleteParameters>
        <asp:Parameter Name="employeeID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

Testare la pagina visitandola tramite un browser. Come illustrato nella figura 14, la pagina elenca ogni dipendente e il nome del suo manager (presupponendo che ne abbiano uno).

Join nella stored procedure Employees_Select restituisce il nome del manager

Figura 14: l'oggetto JOIN nella Employees_Select stored procedure restituisce il nome del manager (fare clic per visualizzare l'immagine a dimensione intera)

Facendo clic sul pulsante Elimina viene avviato il flusso di lavoro di eliminazione, che culmina nell'esecuzione della Employees_Delete stored procedure. Tuttavia, l'istruzione tentata DELETE nella stored procedure ha esito negativo a causa di una violazione del vincolo di chiave esterna (vedere la figura 15). In particolare, ogni dipendente ha uno o più record nella Orders tabella, causando l'esito negativo dell'eliminazione.

L'eliminazione di un dipendente con ordini corrispondenti comporta una violazione del vincolo di chiave esterna

Figura 15: Eliminazione di un dipendente con ordini corrispondenti genera una violazione del vincolo di chiave esterna (fare clic per visualizzare l'immagine a dimensione intera)

Per consentire l'eliminazione di un dipendente, è possibile:

Lascio questo come esercizio per il lettore.

Riepilogo

Quando si usano database relazionali, è comune che le query estraggono i dati da più tabelle correlate. Le sottoquery correlate e JOIN s forniscono due tecniche diverse per l'accesso ai dati dalle tabelle correlate in una query. Nelle esercitazioni precedenti è stato usato in genere di sottoquery correlate perché TableAdapter non può generare INSERTautomaticamente istruzioni , UPDATEe DELETE per le query che coinvolgono JOIN s. Anche se questi valori possono essere forniti manualmente, quando si usano istruzioni SQL ad hoc tutte le personalizzazioni verranno sovrascritte al termine della Configurazione guidata TableAdapter.

Fortunatamente, i tableAdapter creati con stored procedure non soffrono della stessa fragilità di quelle create usando istruzioni SQL ad hoc. Pertanto, è possibile creare un TableAdapter la cui query principale usa un oggetto JOIN quando si usano stored procedure. In questa esercitazione è stato illustrato come creare un tableAdapter di questo tipo. È stata avviata l'uso di una JOINquery -less SELECT per la query principale di TableAdapter in modo che le stored procedure di inserimento, aggiornamento ed eliminazione corrispondenti vengano create automaticamente. Al termine della configurazione iniziale di TableAdapter, la SelectCommand stored procedure è stata aumentata per usare ed JOIN eseguire nuovamente la Configurazione guidata TableAdapter per aggiornare le EmployeesDataTable colonne.

Eseguendo nuovamente la Configurazione guidata TableAdapter, le EmployeesDataTable colonne vengono aggiornate automaticamente in modo da riflettere i campi dati restituiti dalla Employees_Select stored procedure. In alternativa, è possibile aggiungere queste colonne manualmente a DataTable. Nell'esercitazione successiva si esaminerà l'aggiunta manuale di colonne a DataTable.

Buon programmatori!

Informazioni sull'autore

Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, lavora con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto all'indirizzo mitchell@4GuysFromRolla.com. o tramite il suo blog, disponibile all'indirizzo http://ScottOnWriting.NET.

Grazie speciale a

Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali di questa esercitazione sono stati Hilton Geisenow, David Suru e Teresa Murphy. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.