Udostępnij za pośrednictwem


Tworzenie warstwy dostępu do danych (C#)

Autor: Scott Mitchell

Pobierz plik PDF

W tym samouczku zaczniemy od samego początku i utworzymy warstwę dostępu do danych (DAL) przy użyciu typowych zestawów danych, aby uzyskać dostęp do informacji w bazie danych.

Wprowadzenie

Jako deweloperzy sieci Web nasze życie koncentruje się na pracy z danymi. Tworzymy bazy danych do przechowywania danych, kodu w celu ich pobierania i modyfikowania oraz stron internetowych do zbierania i podsumowywania. Jest to pierwszy samouczek z długiej serii, który będzie eksplorować techniki implementowania tych typowych wzorców w ASP.NET 2.0. Zaczniemy od utworzenia architektury oprogramowania składającej się z warstwy dostępu do danych (DAL) przy użyciu typowych zestawów danych, warstwy logiki biznesowej (BLL), która wymusza niestandardowe reguły biznesowe i warstwę prezentacji składającą się z ASP.NET stron, które współużytkują wspólny układ strony. Po ułożeniu tej podstawy zaplecza przejdziemy do raportowania, pokazując, jak wyświetlać, podsumowywać, zbierać i weryfikować dane z aplikacji internetowej. Te samouczki są przeznaczone do zwięzłości i zawierają szczegółowe instrukcje z dużą ilością zrzutów ekranu, aby przejść przez proces wizualnie. Każdy samouczek jest dostępny w wersjach języka C# i Visual Basic oraz zawiera pobieranie kompletnego kodu. (Ten pierwszy samouczek jest dość długi, ale pozostałe są prezentowane w znacznie bardziej szyfrowanych fragmentach).

W przypadku tych samouczków będziemy używać programu Microsoft SQL Server 2005 Express Edition bazy danych Northwind umieszczonej w katalogu App_Data . Oprócz pliku bazy danych folder App_Data zawiera również skrypty SQL służące do tworzenia bazy danych, jeśli chcesz użyć innej wersji bazy danych. Jeśli używasz innej wersji programu SQL Server bazy danych Northwind, musisz zaktualizować ustawienie NORTHWNDConnectionString w pliku Web.config aplikacji. Aplikacja internetowa została skompilowana przy użyciu programu Visual Studio 2005 Professional Edition jako projektu witryny sieci Web opartej na systemie plików. Jednak wszystkie samouczki będą działać równie dobrze z bezpłatną wersją programu Visual Studio 2005, Visual Web Developer.

W tym samouczku zaczniemy od samego początku i utworzymy warstwę dostępu do danych (DAL), a następnie utworzymy warstwę logiki biznesowej (BLL) w drugim samouczku i będziemy pracować nad układem strony i nawigacją w trzecim. Samouczki po trzecim będą oparte na fundamentach określonych w pierwszych trzech. W tym pierwszym samouczku omówiliśmy wiele kwestii, więc uruchom program Visual Studio i zacznijmy!

Krok 1. Tworzenie projektu internetowego i nawiązywanie połączenia z bazą danych

Przed utworzeniem warstwy dostępu do danych (DAL) należy najpierw utworzyć witrynę internetową i skonfigurować bazę danych. Zacznij od utworzenia nowej witryny internetowej opartej na systemie plików ASP.NET. Aby to zrobić, przejdź do menu Plik i wybierz pozycję Nowa witryna sieci Web, wyświetlając okno dialogowe Nowa witryna sieci Web. Wybierz szablon witryny sieci Web ASP.NET, ustaw listę rozwijaną Lokalizacja na System plików, wybierz folder do umieszczania witryny internetowej i ustaw język na C#.

Tworzenie nowej witryny sieci Web opartej na systemie plików

Rysunek 1. Tworzenie nowej witryny sieci Web opartej na systemie plików (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Spowoduje to utworzenie nowej witryny sieci Web ze stroną ASP.NET Default.aspx i folderem App_Data .

Po utworzeniu witryny internetowej następnym krokiem jest dodanie odwołania do bazy danych w Eksploratorze serwera programu Visual Studio. Dodając bazę danych do Eksploratora serwera, można dodawać tabele, procedury składowane, widoki itd. z poziomu programu Visual Studio. Możesz również wyświetlić dane tabeli lub utworzyć własne zapytania ręcznie lub graficznie za pomocą konstruktora zapytań. Ponadto podczas tworzenia typowych zestawów danych dla dal musimy wskazać program Visual Studio do bazy danych, z której powinny być konstruowane typy zestawów danych. Chociaż możemy podać te informacje o połączeniu w tym momencie, program Visual Studio automatycznie wypełnia listę rozwijaną baz danych już zarejestrowanych w Eksploratorze serwera.

Kroki dodawania bazy danych Northwind do Eksploratora serwera zależą od tego, czy chcesz użyć bazy danych programu SQL Server 2005 Express Edition w folderze App_Data , czy też masz konfigurację serwera bazy danych programu Microsoft SQL Server 2000 lub 2005, którego zamiast tego chcesz użyć.

Używanie bazy danych w folderze App_Data

Jeśli nie masz serwera bazy danych programu SQL Server 2000 lub 2005 do nawiązania połączenia lub po prostu chcesz uniknąć konieczności dodawania bazy danych do serwera bazy danych, możesz użyć wersji programu SQL Server 2005 Express Edition bazy danych Northwind znajdującej się w folderze App_Data pobranej witryny internetowej (NORTHWND). MDF).

Baza danych umieszczona w folderze App_Data jest automatycznie dodawana do Eksploratora serwera. Zakładając, że na maszynie jest zainstalowany program SQL Server 2005 Express Edition, powinien zostać wyświetlony węzeł o nazwie NORTHWND. Funkcja MDF w Eksploratorze serwera, którą można rozwinąć i eksplorować jej tabele, widoki, procedurę składowaną itd. (zobacz Rysunek 2).

Folder App_Data może również przechowywać pliki .mdb programu Microsoft Access, które, podobnie jak ich odpowiedniki programu SQL Server, są automatycznie dodawane do Eksploratora serwera. Jeśli nie chcesz używać żadnej z opcji programu SQL Server, zawsze możesz zainstalować bazę danych i aplikacje firmy Northwind Traders i usunąć je w katalogu App_Data . Należy jednak pamiętać, że bazy danych programu Access nie są tak bogate w funkcje jak program SQL Server i nie są przeznaczone do użycia w scenariuszach witryny sieci Web. Ponadto kilka samouczków 35+ będzie korzystać z niektórych funkcji na poziomie bazy danych, które nie są obsługiwane przez program Access.

Nawiązywanie połączenia z bazą danych na serwerze bazy danych programu Microsoft SQL Server 2000 lub 2005

Alternatywnie możesz nawiązać połączenie z bazą danych Northwind zainstalowaną na serwerze bazy danych. Jeśli serwer bazy danych nie ma jeszcze zainstalowanej bazy danych Northwind, należy najpierw dodać ją do serwera bazy danych, uruchamiając skrypt instalacyjny uwzględniony w pobieraniu tego samouczka.

Po zainstalowaniu bazy danych przejdź do Eksploratora serwera w programie Visual Studio, kliknij prawym przyciskiem myszy węzeł Połączenia danych i wybierz polecenie Dodaj połączenie. Jeśli nie widzisz Eksploratora serwera, przejdź do widoku/Eksploratora serwera lub naciśnij Ctrl+Alt+S. Spowoduje to wyświetlenie okna dialogowego Dodawanie połączenia, w którym można określić serwer do nawiązania połączenia, informacje o uwierzytelnieniu i nazwę bazy danych. Po pomyślnym skonfigurowaniu informacji o połączeniu z bazą danych i kliknięciu przycisku OK baza danych zostanie dodana jako węzeł pod węzłem Połączenia danych. Węzeł bazy danych można rozwinąć, aby eksplorować jego tabele, widoki, procedury składowane itd.

Dodawanie połączenia z bazą danych Northwind Serwera bazy danych

Rysunek 2. Dodawanie połączenia z bazą danych northwind serwera bazy danych

Krok 2. Tworzenie warstwy dostępu do danych

Podczas pracy z danymi jedną z opcji jest osadzanie logiki specyficznej dla danych bezpośrednio w warstwie prezentacji (w aplikacji internetowej strony ASP.NET tworzą warstwę prezentacji). Może to mieć formę pisania kodu ADO.NET w części kodu strony ASP.NET lub przy użyciu kontrolki SqlDataSource z części znaczników. W obu przypadkach takie podejście ściśle łączy logikę dostępu do danych z warstwą prezentacji. Zalecane jest jednak oddzielenie logiki dostępu do danych od warstwy prezentacji. Ta oddzielna warstwa jest nazywana warstwą dostępu do danych, dal krótko i jest zwykle implementowana jako oddzielny projekt Biblioteka klas. Zalety tej architektury warstwowej są dobrze udokumentowane (zobacz sekcję "Dalsze informacje" na końcu tego samouczka, aby uzyskać informacje na temat tych zalet) i jest podejściem, które weźmiemy w tej serii.

Cały kod specyficzny dla bazowego źródła danych, taki jak tworzenie połączenia z bazą danych, wydawanie poleceń SELECT, INSERT, UPDATE i DELETE itd. powinno znajdować się w dal. Warstwa prezentacji nie powinna zawierać żadnych odwołań do takiego kodu dostępu do danych, ale zamiast tego powinna wykonywać wywołania do dal dla wszystkich żądań danych. Warstwy dostępu do danych zwykle zawierają metody uzyskiwania dostępu do bazowych danych bazy danych. Na przykład baza danych Northwind zawiera tabele Products and Categories , które rejestrują produkty do sprzedaży i kategorie, do których należą. W naszym dal będziemy mieć takie metody jak:

  • GetCategories(), który zwróci informacje o wszystkich kategoriach
  • GetProducts(), który zwróci informacje o wszystkich produktach
  • GetProductsByCategoryID(categoryID), który zwróci wszystkie produkty należące do określonej kategorii
  • GetProductByProductID(productID), który zwróci informacje o określonym produkcie

Te metody, po wywołaniu, będą łączyć się z bazą danych, wystawiać odpowiednie zapytanie i zwracać wyniki. Sposób zwracania tych wyników jest ważny. Te metody mogą po prostu zwrócić element DataSet lub DataReader wypełniony przez zapytanie bazy danych, ale najlepiej zwracać te wyniki przy użyciu silnie typiowanych obiektów. Obiekt silnie typizowane jest obiektem, którego schemat jest sztywno zdefiniowany w czasie kompilacji, natomiast przeciwieństwo, luźno typizowanego obiektu, jest obiektem, którego schemat nie jest znany do czasu wykonania.

Na przykład obiekty DataReader i DataSet (domyślnie) są luźno typizowane, ponieważ ich schemat jest definiowany przez kolumny zwracane przez zapytanie bazy danych używane do ich wypełnienia. Aby uzyskać dostęp do określonej kolumny z luźno typizowanej tabeli DataTable, musimy użyć składni, takiej jak: DataTable. Wiersze[index]["columnName"]. Luźne wpisywanie tabeli DataTable w tym przykładzie jest wyświetlane przez fakt, że musimy uzyskać dostęp do nazwy kolumny przy użyciu indeksu porządkowego lub ciągu. Z drugiej strony silnie typizowana tabela DataTable będzie mieć każdą z jego kolumn zaimplementowanych jako właściwości, co spowoduje utworzenie kodu, który wygląda następująco: DataTable. Wiersze[indeks].columnName.

Aby zwrócić silnie typizowane obiekty, deweloperzy mogą tworzyć własne niestandardowe obiekty biznesowe lub używać typów zestawów danych. Obiekt biznesowy jest implementowany przez dewelopera jako klasę, której właściwości zwykle odzwierciedlają kolumny tabeli baz danych, którą reprezentuje obiekt biznesowy. Typed DataSet to klasa wygenerowana przez program Visual Studio na podstawie schematu bazy danych i których składowe są silnie typizowane zgodnie z tym schematem. Sam typowy zestaw danych składa się z klas, które rozszerzają klasy ADO.NET DataSet, DataTable i DataRow. Oprócz silnie typiowanych tabel DataTables, typed DataSets zawierają również klasy TableAdapters, które są klasami do wypełniania tabel DataTables i propagowania modyfikacji w tabelach DataTable z powrotem do bazy danych.

Uwaga

Aby uzyskać więcej informacji na temat zalet i wad używania typowych zestawów danych w porównaniu z niestandardowymi obiektami biznesowymi, zobacz Projektowanie składników warstwy danych i przekazywanie danych za pośrednictwem warstw.

Na potrzeby architektury tych samouczków użyjemy silnie typionych zestawów danych. Rysunek 3 przedstawia przepływ pracy między różnymi warstwami aplikacji, która używa typów zestawów danych.

Cały kod dostępu do danych jest zdegradowany do dal

Rysunek 3. Cały kod dostępu do danych jest zdegradowany do dal (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Tworzenie typowego zestawu danych i adaptera tabel

Aby rozpocząć tworzenie naszego dal, zacznijmy od dodania typu zestawu danych do naszego projektu. Aby to osiągnąć, kliknij prawym przyciskiem myszy węzeł projektu w Eksplorator rozwiązań i wybierz polecenie Dodaj nowy element. Wybierz opcję DataSet z listy szablonów i nadaj jej nazwę Northwind.xsd.

Wybierz pozycję Dodaj nowy zestaw danych do projektu

Rysunek 4. Wybieranie pozycji Dodaj nowy zestaw danych do projektu (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po kliknięciu przycisku Dodaj po wyświetleniu monitu o dodanie zestawu danych do folderu App_Code wybierz pozycję Tak. Zostanie wyświetlony projektant typu Zestaw danych, a następnie zostanie uruchomiony Kreator konfiguracji TableAdapter, co umożliwi dodanie pierwszego elementu TableAdapter do typowego zestawu danych.

Typd DataSet służy jako silnie typizowane zbieranie danych; Składa się z silnie typiowanych wystąpień dataTable, z których każda składa się z silnie typiowanych wystąpień datarow. Utworzymy silnie typizowana tabelę DataTable dla każdej z bazowych tabel bazy danych, z którymi musimy pracować w tej serii samouczków. Zacznijmy od utworzenia tabeli DataTable dla tabeli Products .

Należy pamiętać, że silnie typizowane tabele DataTable nie zawierają żadnych informacji na temat uzyskiwania dostępu do danych z podstawowej tabeli bazy danych. Aby pobrać dane w celu wypełnienia tabeli DataTable, użyjemy klasy TableAdapter, która działa jako warstwa dostępu do danych. W przypadku tabeli Products DataTable metoda TableAdapter będzie zawierać metody GetProducts(), GetProductByCategoryID(categoryID)itd., które wywołamy z warstwy prezentacji. Rola tabeli DataTable ma służyć jako silnie typizowane obiekty używane do przekazywania danych między warstwami.

Kreator konfiguracji tableAdapter rozpoczyna się od monitowania o wybranie bazy danych do pracy. Lista rozwijana zawiera te bazy danych w Eksploratorze serwera. Jeśli baza danych Northwind nie została dodana do Eksploratora serwera, możesz teraz kliknąć przycisk Nowe połączenie, aby to zrobić.

Wybierz bazę danych Northwind z listy rozwijanej

Rysunek 5. Wybieranie bazy danych Northwind z listy rozwijanej (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po wybraniu bazy danych i kliknięciu przycisku Dalej zostanie wyświetlony monit o zapisanie parametry połączenia w pliku Web.config. Zapisując parametry połączenia należy unikać kodowania go w klasach TableAdapter, co upraszcza elementy, jeśli parametry połączenia informacje zmieniają się w przyszłości. Jeśli zdecydujesz się zapisać parametry połączenia w pliku konfiguracji, który zostanie umieszczony w <sekcji connectionStrings>, która może być opcjonalnie zaszyfrowana w celu zwiększenia bezpieczeństwa lub modyfikacji później za pomocą nowej strony właściwości ASP.NET 2.0 w narzędziu administratora graficznego interfejsu użytkownika usług IIS, co jest bardziej idealne dla administratorów.

Zapisz parametry połączenia w pliku Web.config

Rysunek 6. Zapisywanie parametrów połączenia w pliku Web.config (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Następnie musimy zdefiniować schemat dla pierwszej silnie typizowanej tabeli DataTable i podać pierwszą metodę, która ma być używana przez klasę TableAdapter podczas wypełniania silnie typizowanego zestawu danych. Te dwa kroki są wykonywane jednocześnie przez utworzenie zapytania zwracającego kolumny z tabeli, które chcemy odzwierciedlić w tabeli DataTable. Na końcu kreatora nadamy nazwę metody temu zapytaniu. Po osiągnięciu tego celu można wywołać tę metodę z warstwy prezentacji. Metoda spowoduje wykonanie zdefiniowanego zapytania i wypełnienie silnie typizowanej tabeli DataTable.

Aby rozpocząć definiowanie zapytania SQL, musimy najpierw wskazać, jak chcemy, aby program TableAdapter wystawił zapytanie. Możemy użyć instrukcji ad hoc SQL, utworzyć nową procedurę składowaną lub użyć istniejącej procedury składowanej. W tych samouczkach użyjemy instrukcji ad hoc SQL.

Wykonywanie zapytań dotyczących danych przy użyciu instrukcji SQL ad hoc

Rysunek 7. Wykonywanie zapytań dotyczących danych przy użyciu instrukcji SQL ad hoc (kliknij, aby wyświetlić obraz pełnowymiarowy)

W tym momencie możemy ręcznie wpisać zapytanie SQL. Podczas tworzenia pierwszej metody w tabeli TableAdapter zwykle zapytanie zwraca te kolumny, które muszą być wyrażone w odpowiedniej tabeli DataTable. Możemy to zrobić, tworząc zapytanie zwracające wszystkie kolumny i wszystkie wiersze z tabeli Products :

Wprowadź zapytanie SQL w polu tekstowym

Rysunek 8. Wprowadź zapytanie SQL w polu tekstowym (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Alternatywnie użyj konstruktora zapytań i graficznie skonstruuj zapytanie, jak pokazano na rysunku 9.

Tworzenie zapytania w sposób graficzny za pomocą Edytor Power Query

Rysunek 9. Tworzenie zapytania graficznego za pomocą Edytor Power Query (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po utworzeniu zapytania, ale przed przejściem na następny ekran kliknij przycisk Opcje zaawansowane. W projektach witryn sieci Web opcja "Generuj instrukcje Wstaw, Aktualizuj i Usuń" jest jedyną opcją zaawansowaną wybraną domyślnie; Jeśli uruchomisz tego kreatora z biblioteki klas lub projektu systemu Windows, zostanie również wybrana opcja "Użyj optymistycznej współbieżności". Pozostaw opcję "Użyj optymistycznej współbieżności" niezaznaczonej na razie. Przeanalizujemy optymistyczną współbieżność w przyszłych samouczkach.

Wybierz opcję Tylko wygeneruj instrukcje Insert, Update i Delete

Rysunek 10. Wybierz opcję Generowanie instrukcji Wstaw, Aktualizuj i Usuń (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po zweryfikowaniu opcji zaawansowanych kliknij przycisk Dalej, aby przejść do ekranu końcowego. W tym miejscu zostanie wyświetlony monit o wybranie metod, które należy dodać do tabeli TableAdapter. Istnieją dwa wzorce wypełniania danych:

  • Wypełnij tabelę DataTable przy użyciu tej metody, która przyjmuje tabelę DataTable jako parametr i wypełnia ją na podstawie wyników zapytania. Na przykład klasa ADO.NET DataAdapter implementuje ten wzorzec za pomocą metody Fill().
  • Zwróć tabelę DataTable przy użyciu tej metody, którą metoda tworzy i wypełnia tabelę DataTable dla Ciebie i zwraca ją jako metodę zwracaną wartość.

Można zaimplementować jeden lub oba te wzorce. Możesz również zmienić nazwy metod podanych tutaj. Pozostawmy zaznaczone oba pola wyboru, mimo że będziemy używać tylko tego ostatniego wzorca w tych samouczkach. Zmieńmy również nazwę raczej ogólnej metody GetData na GetProducts.

Jeśli to pole wyboru, ostatnie pole wyboru "GenerateDBDirectMethods", tworzy metody Insert(), Update()i Delete() dla klasy TableAdapter. Jeśli ta opcja nie zostanie zaznaczona, wszystkie aktualizacje będą musiały zostać wykonane za pomocą jedynej metody Update() klasy TableAdapter, która przyjmuje typed DataSet, DataTable, pojedynczą tabelę DataRow lub tablicę elementów DataRows. (Jeśli nie zaznaczono opcji "Generuj instrukcje Wstaw, Aktualizuj i Usuń" z właściwości zaawansowanych na rysunku 9, to ustawienie tego pola wyboru nie będzie miało żadnego wpływu). Pozostawmy to pole wyboru zaznaczone.

Zmień nazwę metody z GetData na GetProducts

Rysunek 11. Zmień nazwę metody z GetData na GetProducts (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Zakończ pracę kreatora, klikając przycisk Zakończ. Po zamknięciu kreatora wrócimy do projektanta zestawu danych, który pokazuje właśnie utworzoną tabelę DataTable. Listę kolumn można wyświetlić w tabeli Products DataTable (ProductID, ProductName itd.), a także na metodach ProductsTableAdapter (Fill() i GetProducts()).

Produkty DataTable i ProductsTableAdapter zostały dodane do typowanego zestawu danych

Rysunek 12. Element Products DataTable i ProductsTableAdapter zostały dodane do typu zestawu danych (kliknij, aby wyświetlić obraz pełnowymiarowy)

W tym momencie mamy zestaw danych typu z pojedynczą tabelą DataTable (Northwind.Products) i silnie typizowanym klasą DataAdapter (NorthwindTableAdapters.ProductsTableAdapter) metodą GetProducts(). Te obiekty mogą służyć do uzyskiwania dostępu do listy wszystkich produktów z kodu, takiego jak:

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

Ten kod nie wymagał od nas pisania jednego bitu kodu specyficznego dla dostępu do danych. Nie musieliśmy utworzyć wystąpienia żadnych klas ADO.NET, nie musieliśmy odwoływać się do żadnych parametry połączenia, zapytań SQL ani procedur składowanych. Zamiast tego narzędzie TableAdapter udostępnia kod dostępu do danych niskiego poziomu.

Każdy obiekt używany w tym przykładzie jest również silnie typizowany, co umożliwia programowi Visual Studio zapewnienie funkcji IntelliSense i sprawdzania typów w czasie kompilacji. A najlepsze wszystkie tabele danych zwracane przez klasę TableAdapter mogą być powiązane z kontrolkami sieci Web ASP.NET danych, takimi jak GridView, DetailsView, DropDownList, CheckBoxList i kilka innych. Poniższy przykład ilustruje powiązanie tabeli DataTable zwróconej przez metodę GetProducts() do kontrolki GridView w zaledwie trzech wierszach kodu w programie obsługi zdarzeń Page_Load .

AllProducts.aspx

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

AllProducts.aspx.cs

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

Lista produktów jest wyświetlana w siatce

Rysunek 13. Lista produktów jest wyświetlana w siatce (kliknij, aby wyświetlić obraz pełnowymiarowy)

Mimo że w tym przykładzie będziemy pisać trzy wiersze kodu w procedurze obsługi zdarzeń Page_Load ASP.NET strony, w przyszłych samouczkach sprawdzimy, jak deklaratywnie pobrać dane z dal za pomocą obiektu ObjectDataSource. W przypadku obiektu ObjectDataSource nie będziemy musieli pisać żadnego kodu i uzyskać obsługę stronicowania i sortowania.

Krok 3. Dodawanie metod sparametryzowanych do warstwy dostępu do danych

W tym momencie nasza klasa ProductsTableAdapter ma tylko jedną metodę GetProducts(), która zwraca wszystkie produkty w bazie danych. Chociaż możliwość pracy ze wszystkimi produktami jest zdecydowanie przydatna, czasami chcemy pobrać informacje o konkretnym produkcie lub wszystkich produktach należących do określonej kategorii. Aby dodać takie funkcje do warstwy dostępu do danych, możemy dodać metody sparametryzowane do tabeli TableAdapter.

Dodajmy metodę GetProductsByCategoryID(categoryID). Aby dodać nową metodę do dal, wróć do projektanta zestawu danych, kliknij prawym przyciskiem myszy w sekcji ProductsTableAdapter i wybierz polecenie Dodaj zapytanie.

Kliknij prawym przyciskiem myszy kontrolkę TableAdapter i wybierz polecenie Dodaj zapytanie

Rysunek 14. Kliknij prawym przyciskiem myszy kontrolkę TableAdapter i wybierz polecenie Dodaj zapytanie

Najpierw zostanie wyświetlony monit o to, czy chcemy uzyskać dostęp do bazy danych przy użyciu instrukcji AD-hoc SQL, czy nowej lub istniejącej procedury składowanej. Ponownie użyjemy instrukcji ad hoc SQL. Następnie zapytamy, jakiego typu zapytanie SQL chcemy użyć. Ponieważ chcemy zwrócić wszystkie produkty należące do określonej kategorii, chcemy napisać instrukcję SELECT zwracającą wiersze.

Wybierz, aby utworzyć instrukcję SELECT, która zwraca wiersze

Rysunek 15. Wybierz opcję utworzenia instrukcji SELECT , która zwraca wiersze (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Następnym krokiem jest zdefiniowanie zapytania SQL używanego do uzyskiwania dostępu do danych. Ponieważ chcemy zwrócić tylko te produkty należące do określonej kategorii, używam tej samej instrukcji SELECT z getProducts(), ale dodaj następującą klauzulę WHERE : WHERE CategoryID = @CategoryID. Parametr @CategoryID wskazuje kreatora TableAdapter, że metoda, którą tworzymy, będzie wymagać parametru wejściowego odpowiedniego typu (a mianowicie liczby całkowitej dopuszczającej wartość null).

Wprowadź zapytanie, aby zwracać tylko produkty w określonej kategorii

Rysunek 16. Wprowadź zapytanie, aby zwracać tylko produkty w określonej kategorii (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

W ostatnim kroku możemy wybrać wzorce dostępu do danych do użycia, a także dostosować nazwy wygenerowanych metod. W przypadku wzorca Wypełnienia zmieńmy nazwę na FillByCategoryID i dla zwracania wzorca zwracanego w tabeli DataTable (metody GetX) użyjemy identyfikatora GetProductsByCategoryID.

Wybieranie nazw metod TableAdapter

Rysunek 17. Wybieranie nazw metod TableAdapter (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy kreatora projektant zestawu danych zawiera nowe metody TableAdapter.

Zapytania o produkty można teraz wykonywać według kategorii

Rysunek 18. Zapytania dotyczące produktów można teraz wykonywać według kategorii

Pośmiń chwilę, aby dodać metodę GetProductByProductID(productID) przy użyciu tej samej techniki.

Te sparametryzowane zapytania można przetestować bezpośrednio z poziomu projektanta zestawu danych. Kliknij prawym przyciskiem myszy metodę w tabeli TableAdapter i wybierz pozycję Podgląd danych. Następnie wprowadź wartości, które mają być używane dla parametrów, a następnie kliknij pozycję Podgląd.

Te produkty należące do kategorii napojów są wyświetlane

Rysunek 19. Te produkty należące do kategorii Napojów są wyświetlane (kliknij, aby wyświetlić obraz pełnowymiarowy)

Za pomocą metody GetProductsByCategoryID(categoryID) w naszym dal możemy teraz utworzyć stronę ASP.NET, która wyświetla tylko te produkty w określonej kategorii. W poniższym przykładzie przedstawiono wszystkie produkty, które znajdują się w kategorii Napoje, które mają wartość CategoryID 1.

Beverages.asp

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

Beverages.aspx.cs

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

Te produkty w kategorii Napojów są wyświetlane

Rysunek 20. Wyświetlane są produkty w kategorii Napojów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 4. Wstawianie, aktualizowanie i usuwanie danych

Istnieją dwa wzorce często używane do wstawiania, aktualizowania i usuwania danych. Pierwszy wzorzec, który wywołam wzorzec bezpośredni bazy danych, obejmuje tworzenie metod, które podczas wywoływania wystawiają polecenie INSERT, UPDATE lub DELETE do bazy danych działającej na jednym rekordzie bazy danych. Takie metody są zwykle przekazywane w serii wartości skalarnych (liczb całkowitych, ciągów, wartości logicznych, datetimes itd.), które odpowiadają wartościom do wstawiania, aktualizowania lub usuwania. Na przykład z tym wzorcem dla tabeli Products metoda delete będzie przyjmować parametr liczby całkowitej, wskazując identyfikator ProductID rekordu do usunięcia, podczas gdy metoda insert będzie przyjmować ciąg dla ProductName, dziesiętny dla UnitPrice, liczbę całkowitą dla UnitsOnStock itd.

Każde żądanie wstawiania, aktualizowania i usuwania jest wysyłane natychmiast do bazy danych

Rysunek 21. Każde żądanie wstawiania, aktualizowania i usuwania jest wysyłane natychmiast do bazy danych (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Innym wzorcem, który nazywam wzorcem aktualizacji wsadowej, jest zaktualizowanie całego zestawu danych, tabeli DataTable lub kolekcji DataRows w jednym wywołaniu metody. Za pomocą tego wzorca deweloper usuwa, wstawia i modyfikuje wartości DataRows w tabeli DataTable, a następnie przekazuje te wartości DataRows lub DataTable do metody aktualizacji. Następnie ta metoda wylicza przekazane wartości DataRows, określa, czy zostały zmodyfikowane, dodane lub usunięte (za pośrednictwem wartości właściwości RowState elementu DataRow) i wystawiają odpowiednie żądanie bazy danych dla każdego rekordu.

Wszystkie zmiany są synchronizowane z bazą danych po wywołaniu metody aktualizacji

Rysunek 22. Wszystkie zmiany są synchronizowane z bazą danych po wywołaniu metody aktualizacji (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Narzędzie TableAdapter domyślnie używa wzorca aktualizacji wsadowej, ale obsługuje również wzorzec bezpośredni bazy danych. Ponieważ podczas tworzenia tabeli TableAdapter wybrano opcję "Generuj instrukcje Wstaw, Aktualizuj i Usuń" z właściwości zaawansowanych, metoda ProductsTableAdapter zawiera metodę Update(), która implementuje wzorzec aktualizacji wsadowej. W szczególności metoda TableAdapter zawiera metodę Update(), którą można przekazać typed DataSet, silnie typizowaną tabelę DataTable lub co najmniej jedną tabelę DataRows. Jeśli pole wyboru "GenerateDBDirectMethods" zostało zaznaczone podczas pierwszego tworzenia wzorca bezpośredniego bazy danych TableAdapter, zostanie również zaimplementowane za pomocą metod Insert(), Update()i Delete().

Oba wzorce modyfikacji danych używają właściwości InsertCommand, UpdateCommand i DeleteCommand programu TableAdapter do wydawania poleceń INSERT, UPDATE i DELETE do bazy danych. Możesz sprawdzić i zmodyfikować właściwości InsertCommand, UpdateCommand i DeleteCommand, klikając element TableAdapter w Projektancie zestawu danych, a następnie przechodząc do okno Właściwości. (Upewnij się, że wybrano element TableAdapter i że element Obiekt ProductsTableAdapter jest obiektem wybranym na liście rozwijanej w okno Właściwości).

Obiekt TableAdapter ma właściwości InsertCommand, UpdateCommand i DeleteCommand

Rysunek 23. Obiekt TableAdapter ma właściwości InsertCommand, UpdateCommand i DeleteCommand (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Aby zbadać lub zmodyfikować dowolne z tych właściwości polecenia bazy danych, kliknij podwłaściwość CommandText , która spowoduje wyświetlenie Konstruktora zapytań.

Konfigurowanie instrukcji INSERT, UPDATE i DELETE w konstruktorze zapytań

Rysunek 24. Konfigurowanie instrukcji INSERT, UPDATE i DELETE w konstruktorze zapytań (kliknij, aby wyświetlić obraz pełnowymiarowy)

Poniższy przykład kodu pokazuje, jak za pomocą wzorca aktualizacji wsadowej podwoić cenę wszystkich produktów, które nie zostały wycofane i które mają 25 jednostek w magazynie lub mniej:

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

Poniższy kod ilustruje, jak za pomocą wzorca bezpośredniego bazy danych programowo usunąć określony produkt, a następnie zaktualizować go, a następnie dodać nowy:

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

Tworzenie niestandardowych metod wstawiania, aktualizowania i usuwania

Metody Insert(), Update()i Delete() utworzone przez metodę bezpośrednią bazy danych mogą być nieco kłopotliwe, zwłaszcza w przypadku tabel z wieloma kolumnami. Patrząc na poprzedni przykład kodu, bez pomocy intelliSense nie jest szczególnie jasne, co kolumna tabeli Products mapuje na każdy parametr wejściowy do metod Update() i Insert(). Czasami możemy zaktualizować tylko jedną kolumnę lub dwie lub chcieć dostosować metodę Insert(), która na przykład zwróci wartość nowo wstawionego pola IDENTITY (auto-increment).

Aby utworzyć taką metodę niestandardową, wróć do projektanta zestawu danych. Kliknij prawym przyciskiem myszy element TableAdapter i wybierz polecenie Dodaj zapytanie, wracając do kreatora TableAdapter. Na drugim ekranie możemy wskazać typ zapytania do utworzenia. Utwórzmy metodę, która dodaje nowy produkt, a następnie zwraca wartość identyfikatora ProductID nowo dodanego rekordu. W związku z tym wybierz opcję utworzenia zapytania INSERT .

Tworzenie metody w celu dodania nowego wiersza do tabeli Products

Rysunek 25. Tworzenie metody dodawania nowego wiersza do tabeli Products (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Na następnym ekranie zostanie wyświetlony tekst CommandText polecenia InsertCommand. Rozszerz to zapytanie, dodając pozycję SELECT SCOPE_IDENTITY() na końcu zapytania, co spowoduje zwrócenie ostatniej wartości tożsamości wstawionej do kolumny IDENTITY w tym samym zakresie. (Zapoznaj się z dokumentacją techniczną, aby uzyskać więcej informacji na temat SCOPE_IDENTITY() i dlaczego prawdopodobnie chcesz używać SCOPE_IDENTITY() zamiast @@IDENTITY). Przed dodaniem instrukcji SELECT upewnij się, że instrukcja INSERT kończy się średnikiem.

Rozszerzanie zapytania w celu zwrócenia wartości SCOPE_IDENTITY()

Rysunek 26. Rozszerzanie zapytania w celu zwrócenia wartości SCOPE_IDENTITY() (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Na koniec nadaj nowej metodzie nazwę InsertProduct.

Ustaw nową nazwę metody na InsertProduct

Rysunek 27. Ustaw nową nazwę metody na InsertProduct (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po powrocie do projektanta Zestawu danych zobaczysz, że element ProductsTableAdapter zawiera nową metodę InsertProduct. Jeśli ta nowa metoda nie ma parametru dla każdej kolumny w tabeli Products , prawdopodobnie nie pamiętasz zakończenia instrukcji INSERT średnikiem. Skonfiguruj metodę InsertProduct i upewnij się, że masz średnik rozdzielania instrukcji INSERT i SELECT .

Domyślnie metody wstawiania wystawiają metody inne niż zapytania, co oznacza, że zwracają liczbę wierszy, których dotyczy problem. Jednak chcemy , aby metoda InsertProduct zwróciła wartość zwróconą przez zapytanie, a nie liczbę wierszy, których dotyczy problem. Aby to osiągnąć, dostosuj właściwość ExecuteMode metody InsertProduct do wartości Skalarna.

Zmień właściwość ExecuteMode na Skalarną

Rysunek 28. Zmień właściwość ExecuteMode na Skalar (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Poniższy kod przedstawia nową metodę InsertProduct w akcji:

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

Krok 5. Kończenie warstwy dostępu do danych

Należy pamiętać, że klasa ProductsTableAdapters zwraca wartości CategoryID i SupplierID z tabeli Products , ale nie zawiera kolumny CategoryName z tabeli Categories lub kolumny CompanyName z tabeli Dostawcy , chociaż prawdopodobnie są to kolumny, które chcemy wyświetlić podczas wyświetlania informacji o produkcie. Możemy rozszerzyć początkową metodę TableAdapter, GetProducts(), aby uwzględnić zarówno wartości kolumn CategoryName , jak i CompanyName , które zaktualizują silnie typizowana tabelę DataTable, aby uwzględnić również te nowe kolumny.

Może to jednak stanowić problem, ponieważ metody metody tableAdapter do wstawiania, aktualizowania i usuwania danych są oparte na tej początkowej metodzie. Na szczęście automatyczne metody wstawiania, aktualizowania i usuwania nie mają wpływu na podzapytania w klauzuli SELECT . Dbając o dodanie zapytań do kategorii i dostawców jako podzapytania, a nie funkcji JOIN, unikamy konieczności przerobienia tych metod modyfikowania danych. Kliknij prawym przyciskiem myszy metodę GetProducts() w tabeli ProductsTableAdapter i wybierz polecenie Konfiguruj. Następnie dostosuj klauzulę SELECT , aby wyglądała następująco:

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

Aktualizowanie instrukcji SELECT dla metody GetProducts()

Rysunek 29. Aktualizowanie instrukcji SELECT dla metody GetProducts() (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Po zaktualizowaniu metody GetProducts() w celu użycia tego nowego zapytania tabela DataTable będzie zawierać dwie nowe kolumny: CategoryName i SupplierName.

Tabela Danych produktów ma dwie nowe kolumny

Rysunek 30. Tabela danych produktów ma dwie nowe kolumny

Pośmiń chwilę na zaktualizowanie klauzuli SELECT w metodzie GetProductsByCategoryID(categoryID).

Jeśli zaktualizujesz metodę GetProducts() SELECT przy użyciu składni JOIN, projektant zestawu danych nie będzie mógł automatycznie wygenerować metod wstawiania, aktualizowania i usuwania danych bazy danych przy użyciu wzorca bezpośredniego bazy danych. Zamiast tego musisz ręcznie utworzyć je podobnie jak w przypadku metody InsertProduct wcześniej w tym samouczku. Ponadto należy ręcznie podać wartości właściwości InsertCommand, UpdateCommand i DeleteCommand, jeśli chcesz użyć wzorca aktualizacji wsadowej.

Dodawanie pozostałych elementów TableAdapters

Do tej pory przyjrzeliśmy się tylko pracy z pojedynczą tabelą TableAdapter dla pojedynczej tabeli bazy danych. Jednak baza danych Northwind zawiera kilka powiązanych tabel, z którymi będziemy musieli pracować w naszej aplikacji internetowej. Typowy zestaw danych może zawierać wiele powiązanych tabel Danych. W związku z tym, aby ukończyć nasze dal, musimy dodać tabele DataTables dla innych tabel, których będziemy używać w tych samouczkach. Aby dodać nowy element TableAdapter do typowego zestawu danych, otwórz projektanta zestawu danych, kliknij prawym przyciskiem myszy w Projektancie i wybierz polecenie Dodaj/TableAdapter. Spowoduje to utworzenie nowej tabeli DataTable i tabeliAdapter oraz przejrzenie kreatora, który omówiliśmy wcześniej w tym samouczku.

Utworzenie następujących metod TableAdapters i metod przy użyciu następujących zapytań może potrwać kilka minut. Należy pamiętać, że zapytania w tabeli ProductsTableAdapter obejmują podzapytania do ściągnięcia kategorii i nazw dostawców każdego produktu. Ponadto, jeśli wykonano następujące czynności, dodano już metody GetProducts() klasy ProductsTableAdapter i GetProductsByCategoryID(categoryID).

  • ProductsTableAdapter

    • GetProducts:

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

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

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

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

    • GetCategories:

      SELECT     CategoryID, CategoryName, Description
      FROM         Categories
      
    • GetCategoryByCategoryID:

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

    • GetSuppliers:

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

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

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

    • GetEmployees:

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

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

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

Projektant zestawu danych po dodaniu czterech elementów TableAdapters

Rysunek 31. Projektant zestawu danych po dodaniu czterech elementów TableAdapters (kliknij, aby wyświetlić obraz pełnowymiarowy)

Dodawanie kodu niestandardowego do dal

Tabele TableAdapters i DataTables dodane do typed DataSet są wyrażane jako plik definicji schematu XML (Northwind.xsd). Te informacje o schemacie można wyświetlić, klikając prawym przyciskiem myszy plik Northwind.xsd w Eksplorator rozwiązań i wybierając polecenie Wyświetl kod.

Plik definicji schematu XML (XSD) dla typu DataSet northwinds

Rysunek 32. Plik definicji schematu XML (XSD) dla elementu Northwinds Typed DataSet (kliknij, aby wyświetlić obraz pełnowymiarowy)

Te informacje o schemacie są tłumaczone na kod C# lub Visual Basic w czasie projektowania podczas kompilowania lub w czasie wykonywania (w razie potrzeby), w którym momencie można przejść przez nie za pomocą debugera. Aby wyświetlić ten automatycznie wygenerowany kod, przejdź do widoku klas i przejdź do szczegółów klas TableAdapter lub Typed DataSet. Jeśli na ekranie nie widzisz widoku klasy, przejdź do menu Widok i wybierz go z tego miejsca lub naciśnij Ctrl+Shift+C. W widoku klasy można wyświetlić właściwości, metody i zdarzenia klas Typed DataSet i TableAdapter. Aby wyświetlić kod dla określonej metody, kliknij dwukrotnie nazwę metody w widoku klasy lub kliknij ją prawym przyciskiem myszy i wybierz polecenie Przejdź do definicji.

Sprawdź wygenerowany automatycznie kod, wybierając pozycję Przejdź do definicji z widoku klasy

Rysunek 33. Sprawdzanie kodu wygenerowanego automatycznie przez wybranie pozycji Przejdź do definicji w widoku klasy

Chociaż kod generowany automatycznie może być doskonałym oszczędzaniem czasu, kod jest często bardzo ogólny i musi być dostosowany do unikatowych potrzeb aplikacji. Ryzyko rozszerzenia automatycznie wygenerowanego kodu polega jednak na tym, że narzędzie, które wygenerowało kod, może zdecydować, że nadszedł czas na "ponowne wygenerowanie" i zastąpienie dostosowań. Dzięki nowej koncepcji klasy częściowej platformy .NET 2.0 można łatwo podzielić klasę na wiele plików. Dzięki temu możemy dodawać własne metody, właściwości i zdarzenia do klas generowanych automatycznie bez konieczności martwienia się o zastępowanie naszych dostosowań przez program Visual Studio.

Aby zademonstrować sposób dostosowywania dal, dodajmy metodę GetProducts() do klasy SuppliersRow . Klasa SuppliersRow reprezentuje pojedynczy rekord w tabeli Dostawcy ; każdy dostawca może dostarczyć zero do wielu produktów, więc GetProducts() zwróci te produkty określonego dostawcy. Aby to zrobić, utwórz nowy plik klasy w folderze App_Code o nazwie SuppliersRow.cs i dodaj następujący kod:

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

Ta klasa częściowa instruuje kompilator, że podczas kompilowania klasy Northwind.SuppliersRow w celu uwzględnienia właśnie zdefiniowanej metody GetProducts(). Jeśli skompilujesz projekt, a następnie wrócisz do widoku klasy, zobaczysz polecenie GetProducts() teraz jako metodę Northwind.SuppliersRow.

Metoda GetProducts() jest teraz częścią klasy Northwind.SuppliersRow

Rysunek 34. Metoda GetProducts() jest teraz częścią klasy Northwind.SuppliersRow

Metoda GetProducts() może teraz służyć do wyliczania zestawu produktów dla określonego dostawcy, jak pokazano w poniższym kodzie:

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

Te dane mogą być również wyświetlane na dowolnej platformie ASP. Kontrolki sieci Web danych platformy NET. Poniższa strona używa kontrolki GridView z dwoma polami:

  • Pole powiązane, które wyświetla nazwę każdego dostawcy i
  • Pole TemplateField zawierające kontrolkę BulletedList, która jest powiązana z wynikami zwróconymi przez metodę GetProducts() dla każdego dostawcy.

W przyszłych samouczkach dowiemy się, jak wyświetlać takie raporty ze szczegółami głównymi. Na razie ten przykład został zaprojektowany tak, aby zilustrować użycie metody niestandardowej dodanej do klasy Northwind.SuppliersRow .

SuppliersAndProducts.aspx

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

SuppliersAndProducts.aspx.cs

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

Nazwa firmy dostawcy jest wymieniona w lewej kolumnie, ich produkty po prawej stronie

Rysunek 35. Nazwa firmy dostawcy znajduje się w lewej kolumnie, ich produkty po prawej stronie (kliknij, aby wyświetlić obraz pełnowymiarowy)

Podsumowanie

Podczas tworzenia aplikacji internetowej tworzącej dal należy wykonać jeden z pierwszych kroków przed rozpoczęciem tworzenia warstwy prezentacji. W programie Visual Studio utworzenie dal opartego na typowych zestawach danych to zadanie, które można wykonać w ciągu 10–15 minut bez konieczności pisania wiersza kodu. Samouczki będą się rozwijać na podstawie tego dal. W następnym samouczku zdefiniujemy szereg reguł biznesowych i zobaczymy, jak zaimplementować je w oddzielnej warstwie logiki biznesowej.

Szczęśliwe programowanie!

Dalsze informacje

Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:

Szkolenie wideo dotyczące tematów zawartych w tym samouczku

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 24 godzinach. Można go uzyskać 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 omówiona przez wielu przydatnych recenzentów. W tym samouczku recenzenci byli Ron Green, Hilton Giesenow, Dennis Patterson, Liz Shulok, Abel Gomez i Carlos Santos. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.