Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Autor : Scott Mitchell
Podczas pracy z bazą danych często żąda się danych rozmieszczonych w wielu tabelach. Aby pobrać dane z dwóch różnych tabel, możemy użyć skorelowanego podzapytania lub operacji JOIN. W tym samouczku porównaliśmy skorelowane podzapytania i składnię JOIN przed sprawdzeniem, jak utworzyć tabelę TableAdapter zawierającą element JOIN w zapytaniu głównym.
Wprowadzenie
W przypadku relacyjnych baz danych dane, które nas interesują, są często rozmieszczone na wielu tabelach. Na przykład podczas wyświetlania informacji o produkcie prawdopodobnie chcemy wyświetlić listę poszczególnych produktów odpowiadających im kategorii i nazw dostawców. Tabela Products zawiera CategoryID i SupplierID wartości, ale rzeczywiste nazwy kategorii i dostawców znajdują się w tabelach Categories i Suppliers, odpowiednio.
Aby pobrać informacje z innej, powiązanej tabeli, możemy użyć skorelowanych podzapytania lub JOINs. Skorelowane podzapytanie to zagnieżdżone SELECT zapytanie, które odwołuje się do kolumn w zapytaniu głównym. Na przykład w samouczku Tworzenie warstwy dostępu do danych użyliśmy dwóch skorelowanych podzapytania w ProductsTableAdapter głównym zapytaniu, aby zwrócić kategorię i nazwy dostawców dla każdego produktu. A JOIN to konstrukcja SQL, która scala powiązane wiersze z dwóch różnych tabel. Użyliśmy elementu JOIN w samouczku Wykonywanie zapytań o dane za pomocą kontrolki SqlDataSource, aby wyświetlać informacje o kategorii obok każdego produktu.
Powodem, dla którego wstrzymaliśmy się od używania elementów JOIN z TableAdapters, są ograniczenia kreatora TableAdapter, utrudniające automatyczne generowanie odpowiednich instrukcji INSERT, UPDATE i DELETE. Mówiąc dokładniej, jeśli główne zapytanie TableAdapter zawiera jakiekolwiek JOIN s, TableAdapter nie może automatycznie utworzyć instrukcji ad hoc SQL lub procedur składowanych dla jego InsertCommand, UpdateCommand i DeleteCommand właściwości.
W tym samouczku krótko porównamy i zestawimy skorelowane podzapytania oraz JOIN przed zbadaniem, jak utworzyć TableAdapter, który zawiera JOIN w swoim zapytaniu głównym.
Porównywanie i kontrastowanie skorelowanych podzapytania iJOIN s
Pamiętaj, że ProductsTableAdapter utworzony w pierwszym samouczku w zestawie danych Northwind używa skorelowanych podzapytań do odczytania odpowiedniej kategorii i nazwy dostawcy każdego produktu. Poniżej przedstawiono główne zapytanie ProductsTableAdapter.
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
Dwa skorelowane podzapytania — (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID) i (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) — to SELECT zapytania, które zwracają pojedynczą wartość na produkt jako dodatkową kolumnę w zewnętrznej liście kolumn instrukcji SELECT.
Alternatywnie można użyć elementu JOIN w celu zwrócenia nazwy dostawcy i kategorii każdego produktu. Następujące zapytanie zwraca te same dane wyjściowe co powyższe, ale używa JOIN zamiast podzapytania.
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
Rekordy JOIN z jednej tabeli są scalane z rekordami z innej tabeli na podstawie niektórych kryteriów. Na przykład w powyższym zapytaniu LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID instruuje SQL Server, aby scalono każdy rekord produktu z rekordem kategorii, którego wartość CategoryID odpowiada wartości produktu CategoryID. Połączony rezultat umożliwia pracę z odpowiednimi polami kategorii dla każdego produktu (na przykład CategoryName).
Uwaga / Notatka
JOIN S są często używane podczas wykonywania zapytań dotyczących danych z relacyjnych baz danych. Jeśli dopiero zaczynasz pracować ze JOIN składnią lub chcesz sobie przypomnieć jego użycie, polecam samouczek dotyczący łączeń SQL w W3 Schools. Warto również przeczytać sekcje JOIN i Podstawy podzapytania w SQL Books Online.
Ponieważ JOIN zapytania i skorelowane podzapytania mogą być używane do pobierania powiązanych danych z innych tabel, wielu deweloperów zastanawia się, które podejście wybrać. Wszyscy guru SQL, z którymi rozmawiałem, powiedzieli mniej więcej to samo, że pod względem wydajności tak naprawdę nie ma to znaczenia, ponieważ SQL Server wygeneruje mniej więcej identyczne plany wykonywania. Ich porady to użyć techniki, z którą zespół czuje się najbardziej komfortowo. Warto zauważyć, że po przekazaniu tej porady ci eksperci natychmiast wyrażają swoje preferencje dotyczące JOIN s nad skorelowanymi podzapytaniami.
Podczas tworzenia warstwy dostępu do danych z użyciem Typowanych Zestawów Danych narzędzia działają lepiej z użyciem podzapytań. W szczególności kreator TableAdapter nie wygeneruje automatycznie odpowiednich instrukcji INSERT, UPDATE i DELETE , jeśli główne zapytanie zawiera jakiekolwiek JOIN , ale automatycznie wygeneruje te instrukcje podczas używania skorelowanych podzapytań.
Aby zbadać tę niedociągnięcie, utwórz tymczasowy Typed DataSet w folderze ~/App_Code/DAL. W Kreatorze Konfiguracji TableAdapter wybierz użycie instrukcji SQL ad hoc i wprowadź następujące SELECT zapytanie (patrz Rysunek 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
Rysunek 1. Wprowadź główne zapytanie zawierające JOIN s (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Domyślnie narzędzie TableAdapter automatycznie tworzy INSERT, UPDATE, i DELETE instrukcje na podstawie głównego zapytania. Jeśli klikniesz przycisk Zaawansowane, zobaczysz, że ta funkcja jest włączona. Pomimo tego ustawienia TableAdapter nie będzie w stanie utworzyć instrukcji INSERT, UPDATE i DELETE, ponieważ główne zapytanie zawiera JOIN.
Rysunek 2. Wprowadź główne zapytanie zawierające s JOIN
Kliknij przycisk Zakończ, aby ukończyć pracę kreatora. Na tym etapie projektant zestawu danych będzie obejmował pojedynczy TableAdapter z DataTable, która posiada kolumny dla każdego pola zwróconego w liście kolumn zapytania SELECT. Obejmuje to CategoryName i SupplierName, jak pokazano na rysunku 3.
Rysunek 3. Tabela danych zawiera kolumnę dla każdego pola zwróconego na liście kolumn
Chociaż tabela DataTable zawiera odpowiednie kolumny, parametr TableAdapter nie zawiera wartości właściwości InsertCommand, UpdateCommandi DeleteCommand . Aby to potwierdzić, kliknij element TableAdapter w projektancie, a następnie przejdź do okna Właściwości. Zobaczysz, że właściwości InsertCommand, UpdateCommand i DeleteCommand są ustawione na (Brak).
Rysunek 4: InsertCommand, UpdateCommand, i DeleteCommand właściwości są ustawione na (Brak) (Kliknij, aby wyświetlić obraz w pełnym rozmiarze)
Aby obejść tę trudność, możemy ręcznie podać instrukcje SQL i parametry dla właściwości InsertCommand, UpdateCommand i DeleteCommand za pośrednictwem okna właściwości. Alternatywnie, możemy rozpocząć od skonfigurowania głównego zapytania TableAdaptera, aby nie uwzględniały żadnych JOIN. Pozwoli to na automatyczne wygenerowanie dla nas instrukcji INSERT, UPDATE i DELETE. Po ukończeniu pracy kreatora można ręcznie zaktualizować TableAdapter SelectCommand z okna właściwości, aby zawierał składnię JOIN.
Chociaż to podejście działa, jest bardzo kruche w przypadku korzystania z ad-hoc zapytań SQL, ponieważ za każdym razem, gdy główne zapytanie TableAdaptera jest ponownie skonfigurowane za pomocą kreatora, automatycznie generowane instrukcje INSERT, UPDATE i DELETE są tworzone ponownie. Oznacza to, że wszystkie wprowadzone później dostosowania zostaną utracone, jeśli klikniemy prawym przyciskiem myszy na TableAdapter, wybieżemy Konfiguruj z menu kontekstowego i uruchomimy ponownie kreatora.
Kruchość automatycznie generowanych INSERT, UPDATE i DELETE instrukcji jest na szczęście ograniczona do instrukcji SQL ad hoc. Jeśli TableAdapter używa procedur składowanych, można dostosować procedury SelectCommand, InsertCommand, UpdateCommand lub DeleteCommand i ponownie uruchomić kreator konfiguracji TableAdapter bez obawy, że procedury zostaną zmodyfikowane.
W najbliższych kilku krokach utworzymy TableAdapter, który na początku używa głównego zapytania pomijającego wszelkie JOIN, aby odpowiednie przechowywane procedury wstawiania, aktualizowania i usuwania zostały wygenerowane automatycznie. Następnie zaktualizujemy element SelectCommand tak, aby używał elementu JOIN , który zwraca dodatkowe kolumny z powiązanych tabel. Na koniec utworzymy odpowiednią klasę Warstwy logiki biznesowej i pokażemy, jak używać klasy TableAdapter na stronie internetowej ASP.NET.
Krok 1. Tworzenie obiektu TableAdapter przy użyciu uproszczonego zapytania głównego
Na potrzeby tego samouczka dodamy TableAdapter i silnie typizowany element DataTable dla tabeli Employees w zestawie danych NorthwindWithSprocs. Tabela Employees zawiera ReportsTo pole, które określa EmployeeID menedżera pracownika. Na przykład pracownica Anne Dodsworth ma ReportTo wartość 5, co jest EmployeeID wartości Stevena Buchanana. W związku z tym Anne zgłasza Stevenowi, swojemu menedżerowi. Oprócz raportowania ReportsTo wartości każdego pracownika możemy również pobrać imię ich menedżera. Można to zrobić przy użyciu elementu JOIN. Jednak użycie JOIN podczas początkowego tworzenia TableAdaptera uniemożliwia kreatorowi automatyczne generowanie odpowiednich funkcji wstawiania, aktualizacji i usuwania. W związku z tym zaczniemy od utworzenia obiektu TableAdapter, którego główne zapytanie nie zawiera żadnych JOIN s. Następnie w kroku 2 zaktualizujemy główną składowaną procedurę zapytania, aby pobrać nazwę menedżera za pośrednictwem JOIN.
Rozpocznij od otwarcia zestawu NorthwindWithSprocs danych w folderze ~/App_Code/DAL . Kliknij prawym przyciskiem myszy projektanta, wybierz opcję Dodaj z menu kontekstowego i wybierz element menu TableAdapter. Spowoduje to uruchomienie Kreatora konfiguracji TableAdapter. Jak pokazano na Rysunku 5, poleć kreatorowi, aby utworzył nowe procedury składowane, a następnie kliknij przycisk „Dalej”. Aby odświeżyć wiedzę na temat tworzenia nowych procedur składowanych za pomocą kreatora TableAdapter, zapoznaj się z samouczkiem Tworzenie nowych procedur składowanych dla TableAdapters w Typed DataSet.
Rysunek 5. Wybierz opcję Utwórz nowe procedury składowane (kliknij, aby wyświetlić obraz pełnowymiarowy)
Użyj następującej SELECT instrukcji dla głównego zapytania tableAdapter:
SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees
Ponieważ to zapytanie nie zawiera żadnych JOIN, kreator TableAdapter automatycznie utworzy procedury składowane z odpowiednimi instrukcjami INSERT, UPDATE i DELETE, a także procedurę składowaną do wykonywania zapytania głównego.
Poniższy krok pozwala nam nazwać procedury składowane TableAdapter. Użyj nazw Employees_Select, , Employees_InsertEmployees_Updatei Employees_Delete, jak pokazano na rysunku 6.
Rysunek 6. Nadaj nazwę procedurom przechowywanym TableAdapter (kliknij, aby wyświetlić obraz pełnowymiarowy)
W ostatnim kroku zostanie wyświetlony monit o nadanie nazwy metodom TableAdaptera. Użyj metod Fill i GetEmployees jako nazw metod. Pamiętaj również, aby pozostawić pole wyboru Tworzenie metod wysyłania aktualizacji bezpośrednio do bazy danych (GenerateDBDirectMethods).
Rysunek 7: Nazwij metody TableAdapter Fill i GetEmployees (kliknij, aby wyświetlić obraz pełnowymiarowy)
Po ukończeniu działania kreatora poświęć chwilę na zbadanie procedur składowanych w bazie danych. Powinny zostać wyświetlone cztery nowe: Employees_Select, Employees_Insert, Employees_Update i Employees_Delete. Następnie sprawdź właśnie utworzone elementy EmployeesDataTable i EmployeesTableAdapter. Tabela DataTable zawiera kolumnę dla każdego pola zwróconego przez główne zapytanie. Kliknij pozycję TableAdapter, a następnie przejdź do okna Właściwości. Zobaczysz, że właściwości InsertCommand, UpdateCommand i DeleteCommand są poprawnie skonfigurowane do wywoływania odpowiednich procedur składowanych.
Rysunek 8. Funkcja TableAdapter obejmuje możliwości wstawiania, aktualizowania i usuwania (kliknij, aby wyświetlić obraz pełnowymiarowy)
Po automatycznym utworzeniu, zaktualizowaniu i usunięciu odpowiednich procedur składowanych oraz poprawnej konfiguracji właściwości InsertCommand, UpdateCommand i DeleteCommand, możemy dostosować procedury składowane SelectCommand w celu zwrócenia dodatkowych informacji o menedżerze każdego z pracowników. W szczególności musimy zaktualizować procedurę składowaną Employees_Select, aby użyć JOIN i zwrócić wartości FirstName oraz LastName menedżera. Po zaktualizowaniu procedury składowanej należy zaktualizować tabelę DataTable, aby zawierała te dodatkowe kolumny. Zajmiemy się tymi dwoma zadaniami w krokach 2 i 3.
Krok 2. Dostosowywanie procedury składowanej w celu uwzględnienia elementuJOIN
Przejdź do Eksploratora serwera, następnie do folderu Procedury składowane bazy danych Northwind i otwórz procedurę składowaną Employees_Select. Jeśli ta procedura składowana nie jest widoczna, kliknij prawym przyciskiem myszy folder Procedury składowane i wybierz polecenie Odśwież. Zaktualizuj procedurę składowaną, aby używała elementu , LEFT JOIN aby zwrócić imię i nazwisko menedżera:
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
Po zaktualizowaniu instrukcji SELECT zapisz zmiany, przechodząc do menu Plik i wybierając pozycję Zapisz Employees_Select. Alternatywnie możesz kliknąć ikonę Zapisz na pasku narzędzi lub nacisnąć Ctrl+S. Po zapisaniu zmian kliknij prawym przyciskiem myszy procedurę Employees_Select składowaną w Eksploratorze serwera i wybierz polecenie Wykonaj. Na skutek tego zostanie uruchomiona procedura składowana i wyświetlone wyniki w oknie wyjściowym (zobacz Rysunek 9).
Rysunek 9. Wyniki procedur składowanych są wyświetlane w oknie Danych wyjściowych (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Krok 3. Aktualizowanie kolumn tabeli danych
Na tym etapie, procedura składowana Employees_Select zwraca wartości ManagerFirstName i ManagerLastName, ale w EmployeesDataTable brakuje tych kolumn. Te brakujące kolumny można dodać do tabeli DataTable na jeden z dwóch sposobów:
- Ręcznie — kliknij prawym przyciskiem myszy tabelę DataTable w projektancie zestawu danych, a następnie z menu Dodaj wybierz pozycję Kolumna. Następnie możesz nazwać kolumnę i odpowiednio ustawić jej właściwości.
-
Automatycznie — kreator konfiguracji tabeli TableAdapter zaktualizuje kolumny tabeli DataTable w celu odzwierciedlenia pól zwracanych przez procedurę
SelectCommandskładowaną. W przypadku korzystania z instrukcji ad-hoc SQL, kreator usunie właściwościInsertCommand,UpdateCommandiDeleteCommand, ponieważSelectCommandteraz zawieraJOIN. Jednak w przypadku korzystania z procedur składowanych te właściwości polecenia pozostają nienaruszone.
Omówiliśmy ręczne dodawanie kolumn DataTable w poprzednich samouczkach, w tym Master/Detail przy użyciu listy punktowanej rekordów głównych z listą danych szczegółów i przekazywanie plików, a następnym kroku przyjrzymy się temu procesowi bardziej szczegółowo w nadchodzącym samouczku. W tym samouczku jednak użyjemy podejścia automatycznego za pośrednictwem Kreatora konfiguracji TableAdapter.
Zacznij od kliknięcia prawym przyciskiem myszy na EmployeesTableAdapter i wybrania Konfiguruj z menu kontekstowego. Spowoduje to wyświetlenie kreatora konfiguracji TableAdapter, który zawiera listę procedur przechowywanych używanych do wybierania, wstawiania, aktualizowania i usuwania, wraz z ich zwracanymi wartościami i parametrami (jeśli istnieją). Na rysunku 10 przedstawiono tego kreatora. W tym miejscu widać, że procedura składowana Employees_Select teraz zwraca pola ManagerFirstName i ManagerLastName.
Rysunek 10: Kreator pokazuje zaktualizowaną listę kolumn dla Employees_Select zapytania przechowywanego (kliknij, aby wyświetlić obraz w pełnym rozmiarze)
Zakończ pracę kreatora, klikając Zakończ. Po powrocie do projektanta zestawu danych EmployeesDataTable, element zawiera dwie dodatkowe kolumny: ManagerFirstName i ManagerLastName.
Rysunek 11. Zawiera EmployeesDataTable dwie nowe kolumny (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Aby zilustrować, że zaktualizowana procedura przechowywana Employees_Select jest w użyciu i że możliwości wstawiania, aktualizowania i usuwania rekordów w TableAdapter są nadal dostępne, utwórzmy stronę internetową, która pozwala użytkownikom na wyświetlanie i kasowanie pracowników. Przed utworzeniem takiej strony musimy jednak najpierw utworzyć nową klasę w warstwie logiki biznesowej do pracy z pracownikami z zestawu NorthwindWithSprocs danych. W kroku 4 utworzymy klasę EmployeesBLLWithSprocs . W kroku 5 użyjemy tej klasy ze strony ASP.NET.
Krok 4. Implementowanie warstwy logiki biznesowej
Utwórz nowy plik klasy w folderze ~/App_Code/BLL o nazwie EmployeesBLLWithSprocs.cs. Ta klasa naśladuje semantyka istniejącej EmployeesBLL klasy. Ta nowa klasa udostępnia mniej metod i używa NorthwindWithSprocs zestawu Danych (zamiast zestawu Northwind danych). Dodaj następujący kod do EmployeesBLLWithSprocs klasy .
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;
}
}
Właściwość EmployeesBLLWithSprocs klasy s Adapter zwraca wystąpienie elementu NorthwindWithSprocs DataSet s EmployeesTableAdapter. Jest to używane przez klasę s GetEmployees i metodę DeleteEmployee. Metoda GetEmployees wywołuje odpowiadającą EmployeesTableAdapter metodę GetEmployees s, która wywołuje Employees_Select procedurę składowaną i wypełnia wyniki w elemecie EmployeeDataTable. Metoda DeleteEmployee podobnie wywołuje metodę EmployeesTableAdapter sDelete, która wywołuje procedurę składowaną Employees_Delete.
Krok 5. Praca z danymi w warstwie prezentacji
Po zakończeniu EmployeesBLLWithSprocs zajęć możemy pracować z danymi pracowników za pośrednictwem strony ASP.NET. Otwórz stronę JOINs.aspx w folderze AdvancedDAL, a następnie przeciągnij kontrolkę GridView z Narzędzi do projektanta i ustaw jej właściwość ID na Employees. Następnie z tagu inteligentnego GridView powiąż siatkę z nową kontrolką ObjectDataSource o nazwie EmployeesDataSource.
Skonfiguruj ObjectDataSource, aby używać klasy EmployeesBLLWithSprocs, a następnie na kartach SELECT i DELETE upewnij się, że metody GetEmployees i DeleteEmployee zostały wybrane z list rozwijanych. Kliknij przycisk Zakończ, aby ukończyć konfigurację obiektu ObjectDataSource.
Rysunek 12. Konfigurowanie obiektu ObjectDataSource do używania EmployeesBLLWithSprocs klasy (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Zastosuj metody GetEmployees i DeleteEmployee w ObjectDataSource
Rysunek 13. Korzystanie z obiektu ObjectDataSource przy użyciu metod GetEmployees i DeleteEmployee (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Program Visual Studio doda pole BoundField do kontrolki GridView dla każdej z kolumn EmployeesDataTable. Usuń wszystkie te pola powiązane z wyjątkiem Title, LastName, FirstName, ManagerFirstName, i ManagerLastName, oraz zmień nazwy właściwości HeaderText dla ostatnich czterech pól powiązanych na Nazwisko, Imię, Imię menadżera i Nazwisko menadżera odpowiednio.
Aby umożliwić użytkownikom usuwanie pracowników z tej strony, musimy wykonać dwie czynności. Najpierw poinstruuj element GridView, aby zapewnił możliwości usuwania, zaznaczając opcję Włącz funkcję usuwania z inteligentnej etykiety. Po drugie, zmień właściwość ObjectDataSource z wartości ustawionej przez kreatora ObjectDataSource na wartość domyślną (OldValuesParameterFormatString). Po wprowadzeniu tych zmian, deklaratywne znaczniki GridView i ObjectDataSource powinny wyglądać podobnie do następujących:
<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>
Przetestuj stronę, odwiedzając ją za pośrednictwem przeglądarki. Jak pokazano na rysunku 14, strona wyświetli listę każdego pracownika i nazwiska jego lub jej menedżera, zakładając, że go mają.
Rysunek 14. W JOIN procedurze Employees_Select składowanej zwraca nazwę menedżera (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Kliknięcie przycisku Usuń rozpoczyna proces usuwania, który kończy się wykonaniem procedury składowanej Employees_Delete. Jednak w procedurze składowanej próba DELETE zakończyła się niepowodzeniem z powodu naruszenia ograniczenia klucza obcego (patrz Rysunek 15). W szczególności każdy pracownik ma jeden lub więcej rekordów w Orders tabeli, co uniemożliwia usunięcie.
Rysunek 15. Usunięcie pracownika, który ma powiązane zamówienia, skutkuje naruszeniem ograniczenia klucza obcego (kliknij tutaj, aby zobaczyć obraz w pełnym rozmiarze)
Aby umożliwić usunięcie pracownika, możesz:
- Zaktualizuj ograniczenie klucza obcego, aby umożliwić kaskadowe usuwanie.
- Ręcznie usuń rekordy z
Orderstabeli dla pracowników, których chcesz usunąć, lub - Zaktualizuj procedurę
Employees_Deletetak, aby najpierw usunąć powiązane rekordy z tabeliOrders, zanim usuniesz rekordEmployees. Omówiliśmy tę technikę w samouczku Using Existing Stored Procedures for the Typed DataSet s TableAdapters (Używanie istniejących procedur składowanych dla typów zestawów danych TableAdapters ).
Zostawię to jako ćwiczenie dla czytelnika.
Podsumowanie
Podczas pracy z relacyjnymi bazami danych często zapytania pobierają dane z wielu powiązanych tabel. Skorelowane podzapytania i JOIN udostępniają dwie różne techniki uzyskiwania dostępu do danych z powiązanych tabel w zapytaniu. W poprzednich samouczkach najczęściej używaliśmy skorelowanych podzapytań, ponieważ TableAdapter nie może automatycznie generować INSERT, UPDATE i DELETE dla zapytań obejmujących JOIN. Chociaż te wartości można podać ręcznie, w przypadku korzystania z instrukcji ad hoc SQL wszelkie dostosowania zostaną zastąpione po zakończeniu pracy kreatora konfiguracji TableAdapter.
Na szczęście klasy TableAdapters utworzone przy użyciu procedur składowanych nie cierpią z powodu takiej samej kruchości, jak te utworzone przy użyciu instrukcji SQL ad hoc. W związku z tym można utworzyć obiekt TableAdapter, którego główne zapytanie używa JOIN przy użyciu procedur składowanych. W tym samouczku pokazaliśmy, jak utworzyć taki TableAdapter. Zaczęliśmy od użycia zapytania bez JOINSELECT dla głównego zapytania TableAdapter, aby odpowiednie procedury składowania do wstawiania, aktualizowania i usuwania zostały automatycznie utworzone. Po zakończeniu początkowej konfiguracji narzędzia TableAdapter rozszerzyliśmy SelectCommand procedurę składowaną, aby użyć JOIN, a następnie ponownie uruchomiliśmy kreatora konfiguracji TableAdapter, aby zaktualizować kolumny EmployeesDataTable.
Ponowne uruchomienie Kreatora Konfiguracji TableAdapter automatycznie zaktualizowało EmployeesDataTable kolumny, aby odzwierciedlić pola danych zwracane przez składowaną procedurę Employees_Select. Alternatywnie można było ręcznie dodać te kolumny do tabeli DataTable. W następnym samouczku omówimy ręczne dodawanie kolumn do tabeli DataTable.
Szczęśliwe programowanie!
Informacje o autorze
Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można go uzyskać pod adresem mitchell@4GuysFromRolla.com.
Specjalne podziękowania
Ta seria samouczków została omówiona przez wielu przydatnych recenzentów. Głównymi recenzentami tego samouczka byli Hilton Geisenow, David Suru i Teresa Murphy. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, napisz do mnie na adres mitchell@4GuysFromRolla.com.