Aktualizowanie elementu TableAdapter w celu używania sprzężeń JOIN (C#)

Autor : Scott Mitchell

Pobierz plik PDF

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ć element TableAdapter zawierający element JOIN w zapytaniu głównym.

Wprowadzenie

W przypadku relacyjnych baz danych dane, z którymi jesteśmy zainteresowani, często są rozłożone na wiele tabel. 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 wartości i SupplierID , ale rzeczywista kategoria i nazwy dostawców znajdują się odpowiednio w Categories tabelach i Suppliers .

Aby pobrać informacje z innej, powiązanej tabeli, możemy użyć skorelowanych podzapytania lub JOINs. Skorelowane podzapytanie to zapytanie zagnieżdżone SELECT , które odwołuje się do kolumn w zapytaniu zewnętrznym. 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 JOIN elementu w samouczku Dotyczącym wykonywania zapytań o dane za pomocą kontrolki SqlDataSource , aby wyświetlić informacje o kategorii obok każdego produktu.

Powodem, dla którego wstrzymaliśmy się od używania elementów JOIN s z elementami TableAdapters, jest ograniczenie w kreatorze tableAdapter do automatycznego generowania odpowiednich INSERTinstrukcji , UPDATEi DELETE . Mówiąc dokładniej, jeśli główne zapytanie tableAdapter zawiera jakiekolwiek JOIN s, tableAdapter nie może automatycznie utworzyć ad hoc instrukcji SQL lub procedur składowanych dla jego InsertCommandwłaściwości , UpdateCommandi DeleteCommand .

W tym samouczku krótko porównamy skorelowane podzapytania i JOIN s przed zbadaniem, jak utworzyć element TableAdapter zawierający JOIN s w zapytaniu głównym.

Porównywanie i kontrastowanie skorelowanych podzapytania iJOIN s

Pamiętaj, że utworzony ProductsTableAdapter w pierwszym samouczku w zestawie Northwind danych używa skorelowanych podzapytania w celu przywrócenia odpowiadającej im kategorii i nazwy dostawcy każdego produktu. Poniżej ProductsTableAdapter przedstawiono główne zapytanie.

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 — to SELECT zapytania, które zwracają pojedynczą wartość na produkt jako dodatkową kolumnę na liście kolumn instrukcji zewnętrznej SELECT(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) .

Alternatywnie JOIN można użyć elementu do 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 wartości s 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 LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID w powyższym zapytaniu polecenie nakazuje SQL Server scalenie każdego rekordu produktu z rekordem kategorii, którego CategoryID wartość jest zgodna z wartością CategoryID produktu. Scalony wynik umożliwia pracę z odpowiednimi polami kategorii dla każdego produktu (na przykład CategoryName).

Uwaga

JOIN s są często używane podczas wykonywania zapytań dotyczących danych z relacyjnych baz danych. Jeśli jesteś nowym użytkownikiem JOIN składni lub musisz nieco odświeżyć jego użycie, polecam samouczek dołączania SQL w szkołach W3. Warto również przeczytać sekcjeJOIN Podstawy i Podstawy podzapytaniaksiążek SQL Online.

Ponieważ JOIN s i skorelowane podzapytania mogą służyć do pobierania powiązanych danych z innych tabel, wielu deweloperów pozostawia podstawy i zastanawia się, które podejście do użycia. Wszyscy guru SQL, z którymi rozmawiałem, powiedzieli mniej więcej to samo, że tak naprawdę nie ma znaczenia wydajność mądry, jak SQL Server będzie produkować mniej więcej identyczne plany wykonania. Ich porady, a następnie, jest użycie techniki, z którą ty i Twój zespół są najbardziej wygodne. Warto zauważyć, że po przekazaniu tej porady ci eksperci natychmiast wyrazić swoje preferencje co do JOIN skorelowanych podzapytania.

Podczas tworzenia warstwy dostępu do danych przy użyciu typów zestawów danych narzędzia działają lepiej podczas korzystania z podzapytania. W szczególności kreator tableAdapter nie wygeneruje automatycznie odpowiednich INSERTinstrukcji , UPDATEi DELETE , jeśli główne zapytanie zawiera jakiekolwiek JOIN s, ale automatycznie wygeneruje te instrukcje, gdy używane są skorelowane podzapytania.

Aby zapoznać się z tym niedoborem, utwórz tymczasowy zestaw danych typu w folderze ~/App_Code/DAL . W kreatorze konfiguracji tableAdapter wybierz użycie instrukcji AD-hoc SQL i wprowadź następujące SELECT zapytanie (zobacz 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

Zrzut ekranu przedstawiający okno Kreator konfiguracji narzędzia TableAdaptor z wprowadzonym zapytaniem zawierającym numery JOIN.

Rysunek 1. Wprowadź główne zapytanie zawierające JOIN s (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Domyślnie narzędzie TableAdapter automatycznie tworzy INSERTinstrukcje , UPDATEi DELETE na podstawie głównego zapytania. Jeśli klikniesz przycisk Zaawansowane, zobaczysz, że ta funkcja jest włączona. Pomimo tego ustawienia funkcja TableAdapter nie będzie mogła utworzyć INSERTinstrukcji , UPDATEi DELETE , ponieważ główne zapytanie zawiera JOINelement .

Zrzut ekranu przedstawiający okno Opcje zaawansowane z zaznaczonym polem wyboru Generuj instrukcje Wstaw, Aktualizuj i Usuń.

Rysunek 2. Wprowadź główne zapytanie zawierające s JOIN

Kliknij przycisk Zakończ, aby zakończyć kreatora. W tym momencie Projektant zestawu danych będzie zawierać jeden element TableAdapter z tabelą DataTable z kolumnami dla każdego pola zwróconego na SELECT liście kolumn zapytania. Obejmuje to elementy i SupplierName, jak pokazano na rysunku CategoryName 3.

Tabela DataTable zawiera kolumnę dla każdego pola zwróconego na liście kolumn

Rysunek 3. Tabela danych zawiera kolumnę dla każdego pola zwróconego na liście kolumn

Chociaż tabela DataTable zawiera odpowiednie kolumny, element TableAdapter nie ma wartości dla jej InsertCommandwłaściwości , UpdateCommandi DeleteCommand . Aby to potwierdzić, kliknij element TableAdapter w Projektant, a następnie przejdź do okno Właściwości. Zobaczysz, że InsertCommandwłaściwości , UpdateCommandi DeleteCommand są ustawione na wartość (Brak).

Właściwości InsertCommand, UpdateCommand i DeleteCommand są ustawione na (Brak)

Rysunek 4.InsertCommand Właściwości , UpdateCommandi DeleteCommand mają ustawioną wartość (Brak) (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Aby obejść ten brak, możemy ręcznie podać instrukcje SQL i parametry dla InsertCommandwłaściwości , UpdateCommandi DeleteCommand za pośrednictwem okno Właściwości. Alternatywnie można rozpocząć od skonfigurowania głównego zapytania tableAdapter, aby nie uwzględniać żadnych JOIN s. INSERTPozwoli to automatycznie wygenerować instrukcje , UPDATEiDELETE. Po ukończeniu pracy kreatora można ręcznie zaktualizować tabelę TableAdapter z SelectCommand okno Właściwości tak, aby zawierała składnięJOIN.

To podejście działa, ale jest bardzo kruche w przypadku korzystania z zapytań SQL ad hoc, ponieważ za każdym razem, gdy główne zapytanie tableAdapter jest ponownie skonfigurowane za pośrednictwem kreatora, automatycznie generowane INSERTinstrukcje , UPDATEi DELETE są odtwarzane. Oznacza to, że wszystkie wprowadzone później dostosowania zostaną utracone, jeśli klikniemy prawym przyciskiem myszy element TableAdapter, wybierz polecenie Konfiguruj z menu kontekstowego i ponownie zakończymy pracę kreatora.

Kruchość automatycznie generowanych INSERTinstrukcji , UPDATEi DELETE funkcji TableAdapter jest na szczęście ograniczona do instrukcji ad hoc JĘZYKA SQL. Jeśli narzędzie TableAdapter używa procedur składowanych, można dostosować SelectCommandprocedury składowane , InsertCommand, UpdateCommandlub DeleteCommand i ponownie uruchomić kreatora konfiguracji tableAdapter bez obawy, że procedury składowane zostaną zmodyfikowane.

W kolejnych kilku krokach utworzymy obiekt TableAdapter, który początkowo używa głównego zapytania, które pomija dowolne JOIN s, aby odpowiednie procedury składowane wstawiania, aktualizowania i usuwania zostały wygenerowane automatycznie. Następnie zaktualizujemy element SelectCommand tak, aby używał elementu zwracającego JOIN dodatkowe kolumny z powiązanych tabel. Na koniec utworzymy odpowiednią klasę warstwy logiki biznesowej i pokażemy użycie klasy TableAdapter na stronie internetowej ASP.NET.

Krok 1. Tworzenie obiektu TableAdapter przy użyciu uproszczonego zapytania głównego

Na potrzeby tego samouczka dodamy tabelę TableAdapter i silnie typizowany element DataTable dla Employees tabeli w zestawie NorthwindWithSprocs danych. Tabela Employees zawiera ReportsTo pole, które określiło EmployeeID menedżera pracownika. Na przykład pracownik Anne Dodsworth ma ReportTo wartość 5, czyli EmployeeID Steven Buchanan. 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ć nazwę swojego menedżera. Można to zrobić przy użyciu elementu JOIN. Jednak użycie elementu JOIN podczas początkowego tworzenia obiektu TableAdapter uniemożliwia kreatorowi automatyczne generowanie odpowiednich funkcji wstawiania, aktualizowania 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ą procedurę składowaną zapytania, aby pobrać nazwę menedżera za pośrednictwem .JOIN

Rozpocznij od otwarcia elementu NorthwindWithSprocs DataSet w folderze ~/App_Code/DAL . Kliknij prawym przyciskiem myszy Projektant, wybierz opcję Dodaj z menu kontekstowego i wybierz element menu TableAdapter. Spowoduje to uruchomienie kreatora konfiguracji narzędzia TableAdapter. Jak pokazano na rysunku 5, kreator utworzy nowe procedury składowane i kliknij przycisk Dalej. Aby zapoznać się z modułem odświeżania podczas tworzenia nowych procedur składowanych z poziomu kreatora tableAdapter, zapoznaj się z samouczkiem Creating New Stored Procedures for the Typed DataSet s TableAdapters (Tworzenie nowych procedur składowanych dla typów elementów TableAdapters).

Wybierz opcję Utwórz nowe procedury składowane

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 elementów, kreator tableAdapter automatycznie utworzy procedury składowane z odpowiednimi INSERTinstrukcjami , UPDATEi DELETE , a także procedurą składowaną do wykonywania zapytania głównego.

Poniższy krok umożliwia nadenie nam nazwy procedur składowanych tableAdapter. Użyj nazw Employees_Select, , Employees_InsertEmployees_Updatei Employees_Delete, jak pokazano na rysunku 6.

Nazwij procedury składowane tableAdapter

Rysunek 6. Nadaj nazwę procedur składowanych tableAdapter (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

W ostatnim kroku zostanie wyświetlony monit o nadenie nazwy metod tableAdapter. Użyj metod Fill i GetEmployees jako nazw metod. Pamiętaj również, aby pozostawić pole wyboru Create methods to send updates directly to the database (GenerateDBDirectMethods) (Tworzenie metod wysyłania aktualizacji bezpośrednio do bazy danych (GenerateDBDirectMethods).

Nazwij metody TableAdapter s Fill i GetEmployees

Rysunek 7. Nadaj metodom Fill metody TableAdapter i GetEmployees (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy kreatora poświęć chwilę na sprawdzenie procedur składowanych w bazie danych. Powinny zostać wyświetlone cztery nowe: Employees_Select, , Employees_InsertEmployees_Updatei Employees_Delete. Następnie sprawdź EmployeesDataTable element i EmployeesTableAdapter właśnie utworzony. Tabela Danych zawiera kolumnę dla każdego pola zwróconego przez zapytanie główne. Kliknij pozycję TableAdapter, a następnie przejdź do okno Właściwości. Zobaczysz, że InsertCommandwłaściwości , UpdateCommandi DeleteCommand są poprawnie skonfigurowane do wywoływania odpowiednich procedur składowanych.

TableAdapter obejmuje możliwości wstawiania, aktualizowania i usuwania

Rysunek 8. TabelaAdapter zawiera możliwości wstawiania, aktualizowania i usuwania (kliknij, aby wyświetlić obraz pełnowymiarowy)

Dzięki automatycznemu utworzeniu InsertCommand, aktualizowaniu i usuwaniu procedur składowanych oraz poprawnie skonfigurowanych właściwości , UpdateCommandi DeleteCommand możemy dostosować SelectCommand procedurę składowaną w celu zwrócenia dodatkowych informacji o każdym menedżerze pracownika. W szczególności musimy zaktualizować procedurę Employees_Select składowaną, aby użyć elementu JOIN i zwrócić wartości i LastName menedżeraFirstName. Po zaktualizowaniu procedury składowanej musimy 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

Zacznij od przechodzenia do Eksploratora serwera, przechodzenia do szczegółów folderu Procedury składowane bazy danych Northwind i otwierania Employees_Select procedury składowanej. 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 SELECT instrukcji 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ąć klawisze Ctrl+S. Po zapisaniu zmian kliknij prawym przyciskiem myszy procedurę Employees_Select składowaną w Eksploratorze serwera i wybierz polecenie Wykonaj. Spowoduje to uruchomienie procedury składowanej i wyświetlenie wyników w oknie Dane wyjściowe (zobacz Rysunek 9).

Wyniki procedur składowanych są wyświetlane w oknie danych wyjściowych

Rysunek 9. Wyniki procedur składowanych są wyświetlane w oknie danych wyjściowych (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 3. Aktualizowanie kolumn tabeli danych

W tym momencie Employees_Select procedura składowana zwraca ManagerFirstName wartości i ManagerLastName zwraca je, ale 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 zestawie danych Projektant, 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 tableAdapter zaktualizuje kolumny Tabeli danych, aby odzwierciedlić pola zwrócone przez procedurę SelectCommand składowaną. W przypadku korzystania z instrukcji AD-hoc SQL kreator usunie InsertCommandrównież właściwości , UpdateCommandi DeleteCommand , ponieważ teraz SelectCommand zawiera JOINelement . Jednak w przypadku korzystania z procedur składowanych te właściwości polecenia pozostają nienaruszone.

W poprzednich samouczkach omówiliśmy ręczne dodawanie kolumn DataTable, w tym master /detail Using a Bulleted List of Master Records with a Details DataList and Uploading Files (Tabela danych) i Uploading Files (Tabela danych) i przekażemy pliki, a następnie omówimy ten proces bardziej szczegółowo w następnym samouczku. Na potrzeby tego samouczka użyjemy jednak podejścia automatycznego za pośrednictwem Kreatora konfiguracji tableAdapter.

Zacznij od kliknięcia prawym przyciskiem myszy EmployeesTableAdapter i wybrania pozycji Konfiguruj z menu kontekstowego. Spowoduje to wyświetlenie kreatora konfiguracji tableAdapter, który zawiera listę procedur składowanych używanych do wybierania, wstawiania, aktualizowania i usuwania oraz zwracanych wartości i parametrów (jeśli istnieją). Rysunek 10 przedstawia tego kreatora. W tym miejscu widać, że Employees_Select procedura składowana zwraca ManagerFirstName teraz pola i ManagerLastName .

Kreator wyświetla zaktualizowaną listę kolumn dla procedury składowanej Employees_Select

Rysunek 10. Kreator przedstawia zaktualizowaną listę kolumn dla Employees_Select procedury składowanej (kliknij, aby wyświetlić obraz pełnowymiarowy)

Ukończ pracę kreatora, klikając przycisk Zakończ. Po powrocie do zestawu danych Projektant EmployeesDataTable zawiera dwie dodatkowe kolumny: ManagerFirstName i ManagerLastName.

Tabela EmployeesDataTable zawiera dwie nowe kolumny

Rysunek 11. Zawiera EmployeesDataTable dwie nowe kolumny (kliknij, aby wyświetlić obraz pełnowymiarowy)

Aby zilustrować, że zaktualizowana Employees_Select procedura składowana jest w życie i że funkcje wstawiania, aktualizowania i usuwania obiektu TableAdapter są nadal funkcjonalne, utwórzmy stronę internetową, która umożliwia użytkownikom wyświetlanie i usuwanie 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 na stronie 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, tylko ta nowa zapewnia mniej metod i używa NorthwindWithSprocs zestawu Danych (zamiast Northwind zestawu danych). Dodaj poniższy kod do klasy 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;
    }
}

Właściwość EmployeesBLLWithSprocs klasy zwraca Adapter wystąpienie elementu NorthwindWithSprocs DataSet s EmployeesTableAdapter. Jest to używane przez klasy s GetEmployees i DeleteEmployee metody. Metoda GetEmployees wywołuje odpowiednią GetEmployees metodęEmployeesTableAdapter, która wywołuje Employees_Select procedurę składowaną i wypełnia wyniki w elemecie EmployeeDataTable. Metoda DeleteEmployee podobnie wywołuje metodę EmployeesTableAdapter s Delete , która wywołuje procedurę Employees_Delete składowaną.

Krok 5. Praca z danymi w warstwie prezentacji

Po zakończeniu EmployeesBLLWithSprocs zajęć jesteśmy gotowi do pracy z danymi pracowników za pośrednictwem strony ASP.NET. JOINs.aspx Otwórz stronę w AdvancedDAL folderze i przeciągnij kontrolkę GridView z przybornika na Projektant, ustawiając jej ID właściwość na Employees. Następnie z tagu inteligentnego GridView powiąż siatkę z nową kontrolką ObjectDataSource o nazwie EmployeesDataSource.

Skonfiguruj obiekt ObjectDataSource, aby używać EmployeesBLLWithSprocs klasy, 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ę obiektuDataSource.

Konfigurowanie obiektu ObjectDataSource do używania klasy EmployeesBLLWithSprocs

Rysunek 12. Konfigurowanie obiektu ObjectDataSource do używania EmployeesBLLWithSprocs klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Używanie metod GetEmployees i DeleteEmployeee w obiekcie ObjectDataSource

Rysunek 13. Używanie obiektu GetEmployees ObjectDataSource za pomocą metod i DeleteEmployee (kliknij, aby wyświetlić obraz pełnowymiarowy)

Program Visual Studio doda pole BoundField do kontrolki GridView dla każdej kolumny EmployeesDataTable . Usuń wszystkie te pola boundfield z wyjątkiem Title, , LastNameFirstName, ManagerFirstNamei ManagerLastName zmień nazwy HeaderText właściwości dla ostatnich czterech elementów BoundFields na Last Name, First Name, Manager s First Name i Manager s Last Name, Manager s Last Name( i Manager s Last Name).

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, sprawdzając opcję Włącz usuwanie z tagu inteligentnego. Po drugie zmień właściwość ObjectDataSource OldValuesParameterFormatString z wartości ustawionej przez kreatora ObjectDataSource (original_{0}) na wartość domyślną ({0}). Po wprowadzeniu tych zmian znaczniki deklaratywne 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 będzie wyświetlać listę poszczególnych pracowników i jego nazwiska kierownika (przy założeniu, że mają jeden).

Funkcja JOIN w procedurze składowanej Employees_Select zwraca nazwę menedżera

Rysunek 14. W JOIN procedurze Employees_Select składowanej zwraca nazwę menedżera (kliknij, aby wyświetlić obraz pełnowymiarowy)

Kliknięcie przycisku Usuń powoduje uruchomienie przepływu pracy usuwania, który kończy się wykonaniem Employees_Delete procedury składowanej. Jednak próba instrukcji w procedurze składowanej DELETE kończy się niepowodzeniem z powodu naruszenia ograniczeń klucza obcego (patrz Rysunek 15). W szczególności każdy pracownik ma co najmniej jeden rekord w Orders tabeli, powodując niepowodzenie usuwania.

Usuwanie pracownika z odpowiednimi zamówieniami powoduje naruszenie ograniczenia klucza obcego

Rysunek 15. Usuwanie pracownika z odpowiednimi zamówieniami powoduje naruszenie ograniczenia klucza obcego (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Aby umożliwić usunięcie pracownika, możesz:

Zostawię to jako ćwiczenie dla czytelnika.

Podsumowanie

Podczas pracy z relacyjnymi bazami danych często zdarza się, że zapytania pobierają dane z wielu powiązanych tabel. Skorelowane podquery i JOIN s zapewniają dwie różne techniki uzyskiwania dostępu do danych z powiązanych tabel w zapytaniu. W poprzednich samouczkach najczęściej używaliśmy skorelowanych podquerii, ponieważ narzędzie TableAdapter nie może automatycznie generować INSERTinstrukcji , UPDATEi DELETE dla zapytań obejmujących JOIN s. 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 działania kreatora konfiguracji tableAdapter.

Na szczęście klasy TableAdapters utworzone przy użyciu procedur składowanych nie cierpią z powodu tej samej kruchości, co te utworzone przy użyciu instrukcji AD-hoc SQL. W związku z tym można utworzyć obiekt TableAdapter, którego główne zapytanie używa obiektu JOIN podczas korzystania z procedur składowanych. W tym samouczku pokazano, jak utworzyć taki element TableAdapter. Zaczęliśmy korzystać z JOINzapytania -less SELECT dla głównego zapytania TableAdapter, aby odpowiednie procedury składowane wstawiania, aktualizowania i usuwania zostały automatycznie utworzone. Po zakończeniu początkowej konfiguracji tableAdapter rozszerzyliśmy SelectCommand procedurę składowaną, aby użyć JOIN kreatora konfiguracji TableAdapter i ponownie uruchomić go, aby zaktualizować EmployeesDataTable kolumny.

Ponowne uruchomienie kreatora konfiguracji tableAdapter automatycznie zaktualizowało EmployeesDataTable kolumny w celu odzwierciedlenia pól danych zwracanych przez procedurę Employees_Select składowaną. 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 do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została przejrzyona 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, upuść mi wiersz pod adresemmitchell@4GuysFromRolla.com .