Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Quando si lavora con 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 join nella query principale.
Introduzione
Con i database relazionali i dati con cui si è interessati a lavorare sono spesso distribuiti tra più tabelle. Ad esempio, quando vengono visualizzate informazioni sul prodotto, è probabile che si voglia elencare ogni prodotto corrispondente categoria e nomi dei fornitori. La tabella Products ha valori CategoryID e SupplierID, ma i nomi effettivi delle categorie e dei fornitori si trovano rispettivamente nella tabella Categories e nella tabella 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 abbiamo usato due sottoquery correlate nella ProductsTableAdapter query principale per restituire i nomi di categoria e fornitore per ogni prodotto. Un JOIN è un costrutto SQL che unisce righe correlate da due tabelle diverse. Abbiamo utilizzato un JOIN nel tutorial Querying Data with the SqlDataSource Control per visualizzare le informazioni sulle categorie insieme a ogni prodotto.
Il motivo per cui ci si è astenuti dall'uso di JOIN con gli oggetti TableAdapter è dovuto alle limitazioni della procedura guidata di TableAdapter nel generare automaticamente istruzioni corrispondenti a INSERT, UPDATE e DELETE. In particolare, se la query principale del TableAdapter contiene qualsiasi elemento JOIN, il TableAdapter non può creare automaticamente le istruzioni SQL ad hoc o le stored procedure per le sue proprietà InsertCommand, UpdateCommand e DeleteCommand.
In questa esercitazione verranno brevemente confrontate e messe a confronto sottoquery correlate e JOIN prima di esplorare come creare un TableAdapter che include JOIN nella query principale.
Confronto e contrasto di sottoquery correlate eJOIN s
Tenere presente che l'oggetto ProductsTableAdapter creato nella prima esercitazione nel Northwind DataSet usa sottoquery correlate per riportare, per ciascun prodotto, la categoria e il nome del fornitore corrispondenti. 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 (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID), sono query SELECT che restituiscono un singolo valore per prodotto come colonna aggiuntiva nell'elenco delle colonne dell'istruzione esterna SELECT.
In alternativa, è possibile utilizzare un oggetto JOIN per restituire ogni fornitore e nome di categoria di ogni prodotto. La query seguente restituisce lo stesso output di quello precedente, ma usa s JOIN 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 a 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 categoria corrispondenti per ogni prodotto ( ad esempio CategoryName).
Annotazioni
JOIN s vengono comunemente usati durante l'esecuzione di query sui dati dai database relazionali. Se sei nuovo alla JOIN sintassi o hai bisogno di rinfrescare un po' l'uso, ti consiglio il tutorial su SQL Join su W3 Schools. Vale anche la pena leggere le sezioni JOIN e Nozioni fondamentali sulla sottoquery dei Libri SQL Online.
Poiché le sottoquery JOIN e quelle correlate possono essere entrambe usate per recuperare dati correlati da altre tabelle, molti sviluppatori si trovano a grattarsi la testa, domandandosi quale approccio utilizzare. Tutti i guru di SQL a cui ho parlato hanno detto più o meno la stessa cosa, che dal punto di vista delle prestazioni non importa veramente, dato che SQL Server produrrà piani di esecuzione quasi identici. Il loro consiglio, quindi, è quello di usare la tecnica con cui l'utente e il team sono più a proprio agio. Merita notare che questi esperti esprimono immediatamente la loro preferenza per JOIN rispetto alle sottoquery correlate dopo aver impartito questo consiglio.
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 le istruzioni corrispondenti INSERT, UPDATE e DELETE se la query principale contiene JOIN qualsiasi, 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
Figura 1: Immettere una query principale contenente JOIN s (fare clic per visualizzare l'immagine a dimensione intera)
Per impostazione predefinita, TableAdapter creerà automaticamente le istruzioni INSERT, UPDATE e 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 INSERT, UPDATE e DELETE perché la query principale contiene un oggetto JOIN.
Figura 2: Immettere una query principale contenente JOIN s
Fare clic su Fine per completare la procedura guidata. A questo punto, il progettista di DataSet includerà un singolo TableAdapter con una DataTable che avrà colonne per ciascuno dei campi restituiti nell'elenco delle colonne della query SELECT. Questo include il CategoryName e il SupplierName, come mostrato nella figura 3.
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 le proprietà InsertCommand, UpdateCommand e DeleteCommand. Per confermare questa operazione, fare clic su TableAdapter in Progettazione e quindi passare alla finestra Proprietà. Si noterà che le InsertCommandproprietà , UpdateCommande DeleteCommand sono impostate su (Nessuno).
Figura 4: Le InsertCommandproprietà , UpdateCommande DeleteCommand sono impostate su (Nessuno) (Fare clic per visualizzare l'immagine a dimensione intera)
Per risolvere questo problema, è possibile specificare manualmente le istruzioni e i parametri SQL per le InsertCommandproprietà , UpdateCommande DeleteCommand tramite la finestra Proprietà . In alternativa, è possibile iniziare configurando la query principale dell'oggetto TableAdapter in modo da non includere elementi JOIN . Questo permetterà alle istruzioni INSERT, UPDATE e DELETE di essere generate automaticamente per noi. Dopo aver completato la procedura guidata, è possibile aggiornare manualmente l'oggetto TableAdapter dalla SelectCommand finestra Proprietà in modo che includa la JOIN sintassi.
Sebbene questo approccio funzioni, è 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 INSERT, UPDATE e DELETE, che vengono generate automaticamente, sono 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, scegliere Configura dal menu di scelta rapida e completare di nuovo la procedura guidata.
La fragilità delle istruzioni INSERT, UPDATE e DELETE generate automaticamente da TableAdapter è, fortunatamente, limitata alle istruzioni SQL ad hoc. Se il tuo TableAdapter usa le procedure memorizzate, puoi personalizzare le SelectCommand, InsertCommand, UpdateCommand o DeleteCommand e rieseguire la configurazione guidata del TableAdapter senza temere che le procedure memorizzate vengano modificate.
Nei diversi 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. Aggiorneremo quindi il SelectCommand in modo da utilizzare un JOIN che restituisca colonne aggiuntive dalle tabelle correlate. Infine, verrà creata una classe livello di logica di business corrispondente e verrà illustrato l'uso di TableAdapter in una pagina Web ASP.NET.
Passaggio 1: Creazione di TableAdapter usando una query principale semplificata
Per questa esercitazione aggiungeremo un TableAdapter e un DataTable fortemente tipizzato per la tabella Employees nel DataSet NorthwindWithSprocs. La Employees tabella contiene un ReportsTo campo che specifica il ruolo EmployeeID del responsabile del dipendente. Ad esempio, il dipendente Anne Dodsworth ha un ReportTo valore pari a 5, ovvero di EmployeeID Steven Buchanan. Di conseguenza, Anne riferisce a Steven, il suo manager. Oltre a registrare il valore di ReportsTo per ogni dipendente, potremmo anche voler recuperare il nome del loro responsabile. Questa operazione può essere eseguita usando un oggetto JOIN. Tuttavia, l'uso di un JOIN durante la creazione iniziale del TableAdapter impedisce alla procedura guidata di generare automaticamente le funzionalità corrispondenti di inserimento, aggiornamento ed eliminazione. Pertanto, inizieremo creando un TableAdapter la cui query principale non contiene alcun JOIN. Quindi, nel passaggio 2, aggiorneremo la procedura memorizzata della query principale per recuperare il nome del responsabile tramite un oggetto JOIN.
Per iniziare, aprire l'oggetto NorthwindWithSprocs DataSet nella ~/App_Code/DAL cartella . Fare clic con il pulsante destro del mouse su Designer, selezionare l'opzione Aggiungi dal menu di scelta rapida e scegliere la voce di menu TableAdapter. Questo avvierà la procedura guidata di configurazione di TableAdapter. Come illustrato nella figura 5, fate creare alla procedura guidata nuove stored procedure e fare clic su Avanti. Per un ripasso sulla creazione di nuove stored procedure dalla procedura guidata dei TableAdapter, consultare l'esercitazione Creazione di nuove stored procedure per i TableAdapter del DataSet tipizzato.
Figura 5: Seleziona 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 elementi JOIN, la procedura guidata TableAdapter creerà automaticamente stored procedure con istruzioni INSERT, UPDATE e DELETE corrispondenti, 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.
Figura 6: Denominare le stored procedure di TableAdapter (fare clic per visualizzare l'immagine a schermo intero)
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 aggiornamenti direttamente al database" (GenerateDBDirectMethods).
Figura 7: Denominare i metodi Fill di TableAdapter e GetEmployees (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver completato la procedura guidata, si consiglia di esaminare le stored procedure nel database. Verranno visualizzati quattro nuovi: Employees_Select, Employees_Insert, Employees_Updatee Employees_Delete. Esaminare quindi il EmployeesDataTable e il EmployeesTableAdapter appena creati. DataTable contiene una colonna per ogni campo restituito dalla query principale. Fare clic su TableAdapter e quindi passare alla finestra Proprietà. Lì vedrai che le proprietà InsertCommand, UpdateCommand e DeleteCommand sono configurate correttamente per chiamare le procedure memorizzate corrispondenti.
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 InsertCommand, UpdateCommand e DeleteCommand proprietà configurate correttamente, siamo pronti a personalizzare la stored procedure di SelectCommand per restituire informazioni aggiuntive su ogni responsabile di ciascun dipendente. In particolare, è necessario aggiornare la Employees_Select stored procedure per utilizzare un JOIN e restituire i valori di FirstName e LastName del gestore. Dopo l'aggiornamento della 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 procedura memorizzata per includere unJOIN
Per iniziare, passare a Esplora risorse del server, esplorare in dettaglio la cartella Procedure Memorizzate del database Northwind e aprire la procedura memorizzata Employees_Select. Se questa stored procedure non viene visualizzata, fare clic con il pulsante destro del mouse sulla cartella Stored procedure e scegliere Aggiorna. Aggiorna la procedura memorizzata in modo che utilizzi un LEFT JOIN 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 mouse sulla Employees_Select 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).
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 stored procedure Employees_Select restituisce i valori ManagerFirstName e ManagerLastName, ma EmployeesDataTable manca di 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 in Progettazione set di dati e scegliere Colonna dal menu Aggiungi. È quindi possibile denominare la colonna e impostarne le proprietà di conseguenza.
-
Automaticamente - la procedura guidata di configurazione TableAdapter aggiornerà le colonne di DataTable in modo da riflettere i campi restituiti dalla
SelectCommandprocedura memorizzata. Quando si usano istruzioni SQL ad hoc, la procedura guidata rimuoverà anche leInsertCommand,UpdateCommandeDeleteCommandproprietà poiché oraSelectCommandcontiene unJOIN. Tuttavia, quando si usano stored procedure, queste proprietà dei comandi rimangono intatte.
Nelle esercitazioni precedenti, abbiamo esplorato l'aggiunta manuale di colonne DataTable, tra cui Master/Detail con un elenco puntato di record principali e un DataList dettagliato e caricamento di file, e esamineremo di nuovo questo processo in modo più approfondito nella prossima esercitazione. Per questa esercitazione, tuttavia, è possibile usare l'approccio automatico tramite la Configurazione guidata TableAdapter.
Per iniziare, fare clic con il pulsante destro su EmployeesTableAdapter e scegliere Configura dal menu di scelta rapida. Apre la procedura guidata di configurazione del TableAdapter, che elenca le stored procedure usate per la selezione, l'inserimento, l'aggiornamento e l'eliminazione, insieme ai relativi valori restituiti e dei parametri (se presenti). La figura 10 illustra questa procedura guidata. Qui possiamo vedere che la stored procedure Employees_Select ora restituisce i campi ManagerFirstName e ManagerLastName.
Figura 10: La procedura guidata mostra l'elenco di colonne aggiornato per la Employees_Select procedura memorizzata (clicca per visualizzare l'immagine a dimensione intera)
Completare la procedura guidata facendo clic su Fine. Quando si torna alla Progettazione DataSet, il EmployeesDataTable include due colonne aggiuntive: ManagerFirstName e ManagerLastName.
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 del "TableAdapter" sono ancora operative, creiamo 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 del NorthwindWithSprocs Set di dati. Nel passaggio 4 verrà creata una EmployeesBLLWithSprocs classe. Nel passaggio 5 si userà questa classe 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 dataset NorthwindWithSprocs anziché DataSet Northwind . 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 NorthwindWithSprocs di DataSet s EmployeesTableAdapter. Viene usato dai metodi della classe GetEmployees e DeleteEmployee. Il metodo GetEmployees chiama il metodo corrispondente EmployeesTableAdapter, che richiama la stored procedure GetEmployees e popola i suoi risultati in un oggetto Employees_Select. Il metodo DeleteEmployee chiama analogamente il metodo EmployeesTableAdapterDelete, che richiama la procedura memorizzata Employees_Delete.
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 Toolbox nel Designer, impostandone la proprietà ID su Employees. Successivamente, dallo smart tag 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.
Figura 12: Configurare ObjectDataSource per l'uso della classe (EmployeesBLLWithSprocs a dimensione intera)
Figura 13: Fare in modo che ObjectDataSource utilizzi i 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 di Title, LastName, FirstName, ManagerFirstName e ManagerLastName e rinominare le proprietà per gli ultimi quattro BoundFields rispettivamente in Cognome, Nome, Nome del manager e Cognome del manager.
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 dal relativo smart tag. In secondo luogo, modificare la proprietà ObjectDataSource s OldValuesParameterFormatString dal valore impostato dalla procedura guidata ObjectDataSource (original_{0}) al valore predefinito ({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 manager (presupponendo che ne abbiano uno).
Figura 14: La JOIN nella stored procedure Employees_Select restituisce il nome del responsabile (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, il tentativo di istruzione DELETE nella stored procedure fallisce a causa di una violazione del vincolo di chiave esterna (vedi Figura 15). In particolare, ogni dipendente ha uno o più record nella tabella Orders, causando il fallimento dell'eliminazione.
Figura 15: Eliminazione di un dipendente con ordini corrispondenti comporta una violazione del vincolo di chiave esterna (fare clic per visualizzare l'immagine a dimensione intera)
Per consentire l'eliminazione di un dipendente, è possibile:
- Aggiornare il vincolo di chiave esterna per attivare le eliminazioni a cascata
- Eliminare manualmente i record dalla
Orderstabella per i dipendenti da eliminare o - Aggiornare la procedura memorizzata
Employees_Deleteper prima eliminare i record correlati dalla tabellaOrdersprima di eliminare il recordEmployees. Questa tecnica è stata discussa nell'esercitazione Using Existing Stored Procedures for the Typed DataSet's TableAdapters.
Lascio questo come esercizio per il lettore.
Riassunto
Quando si usano database relazionali, è comune che le query estraggono i dati da più tabelle correlate. Le sottoquery correlate e JOIN forniscono due tecniche diverse per accedere ai dati dalle tabelle correlate nelle query. Nelle esercitazioni precedenti sono state più comunemente utilizzate sottoquery correlate perché TableAdapter non può generare automaticamente INSERT, UPDATE e 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, gli oggetti TableAdapter creati usando stored procedure non soffrono della stessa fragilità di quelle create usando istruzioni SQL ad hoc. Pertanto, è possibile creare un TableAdapter la cui query principale utilizza JOIN quando si usano procedure memorizzate. In questa esercitazione è stato illustrato come creare un tableadapter di questo tipo. Abbiamo iniziato utilizzando una query senza JOINSELECT per la query principale del TableAdapter in modo che le stored procedure di inserimento, aggiornamento e eliminazione siano create automaticamente. Una volta completata la configurazione iniziale di TableAdapter, abbiamo modificato la procedura memorizzata SelectCommand per utilizzare un JOIN ed eseguito nuovamente la configurazione guidata di TableAdapter per aggiornare le colonne di EmployeesDataTable.
Rieseguendo la procedura guidata di configurazione del TableAdapter, le colonne EmployeesDataTable vengono aggiornate automaticamente per riflettere i campi dati restituiti dalla stored procedure Employees_Select. In alternativa, è possibile aggiungere queste colonne manualmente a DataTable. Nell'esercitazione successiva si esaminerà l'aggiunta manuale di colonne all'oggetto DataTable.
Buon programmatori!
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato 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 a mitchell@4GuysFromRolla.com.
Grazie speciale a
Questa serie di esercitazioni è stata esaminata da molti revisori competenti. I revisori principali per questa esercitazione sono stati Hilton Geisenow, David Suru e Teresa Murphy. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, mandami un messaggio a mitchell@4GuysFromRolla.com.