Sdílet prostřednictvím


Aktualizace komponenty TableAdapter kvůli použití příkazů JOIN (C#)

Scott Mitchell

Stáhnout PDF

Při práci s databází je běžné požadovat data, která jsou rozložená do více tabulek. K načtení dat ze dvou různých tabulek můžeme použít buď korelovaný poddotaz, nebo operaci JOIN. V tomto kurzu porovnáme korelované poddotazy a syntaxi JOIN, než se podíváme na to, jak vytvořit objekt TableAdapter, který do svého hlavního dotazu zahrne join.

Úvod

U relačních databází jsou data, se kterými chceme pracovat, často rozložená do několika tabulek. Například při zobrazení informací o produktu budeme pravděpodobně chtít zobrazit seznam odpovídajících kategorií produktů a názvů dodavatelů. Tabulka Products obsahuje CategoryID hodnoty a SupplierID , ale skutečné názvy kategorií a dodavatelů jsou v Categories tabulkách a Suppliers .

K načtení informací z jiné související tabulky můžeme použít korelované poddotazy nebo JOINs. Korelovaný poddotaz je vnořený SELECT dotaz, který odkazuje na sloupce ve vnějším dotazu. Například v kurzu Vytvoření vrstvy přístupu k datům jsme v ProductsTableAdapter hlavním dotazu použili dva korelované poddotazy, abychom vrátili názvy kategorií a dodavatelů pro každý produkt. A JOIN je konstruktor SQL, který slučuje související řádky ze dvou různých tabulek. V kurzu Dotazování na data s ovládacím prvku SqlDataSource jsme použili JOIN k zobrazení informací o kategoriích vedle jednotlivých produktů.

Důvod, proč jsme se zdržel použití JOIN s s s tableadapter je kvůli omezením v průvodci TableAdapter pro automatické generování odpovídajících INSERTpříkazů , UPDATEa DELETE . Přesněji řečeno, pokud hlavní dotaz objektu TableAdapter obsahuje nějaké JOIN s, objekt TableAdapter nemůže automaticky vytvořit ad hoc příkazy SQL nebo uložené procedury pro jeho InsertCommandvlastnosti , UpdateCommanda DeleteCommand .

V tomto kurzu krátce porovnáme korelované poddotazy a poddotazy a JOIN potom prozkoumáme, jak vytvořit objekt TableAdapter, který do hlavního dotazu zahrne JOIN s.

Porovnání a kontrast korelovaných poddotazů aJOIN poddotazů

Vzpomeňte si, že objekt ProductsTableAdapter vytvořený v prvním kurzu v datové Northwind sadě používá korelované poddotady k vrácení odpovídající kategorie produktu a názvu dodavatele. Hlavní ProductsTableAdapter dotaz je zobrazený níže.

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

Dva korelované poddotazy – (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID) a – jsou SELECT dotazy, které vrací jednu hodnotu na produkt jako další sloupec v seznamu sloupců vnějšího SELECT(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) příkazu.

Alternativně lze použít k JOIN vrácení názvu každého dodavatele produktu a názvu kategorie. Následující dotaz vrátí stejný výstup jako výše uvedený dotaz, ale místo poddotazů používá JOIN s:

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

Sloučí JOIN záznamy z jedné tabulky se záznamy z jiné tabulky na základě určitých kritérií. Například LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID ve výše uvedeném dotazu dává příkaz pokyn, SQL Server sloučit každý záznam o produktu se záznamem kategorie, jehož CategoryID hodnota odpovídá hodnotě produktuCategoryID. Sloučený výsledek nám umožňuje pracovat s odpovídajícími poli kategorií pro každý produkt (například CategoryName).

Poznámka

JOIN s se běžně používají při dotazování dat z relačních databází. Pokud se syntaxí začínáte JOIN nebo potřebujete trochu otěhotnět její použití, doporučuji kurz PŘIPOJENÍ k SQL na W3 Schools. Za přečtení stojí JOIN také oddíly Základy a Základy poddotazů v online službě SQL Books.

Vzhledem k tomu, že JOIN s i korelované poddotazy se dají použít k načtení souvisejících dat z jiných tabulek, mnoho vývojářů si rýpne hlavu a zajímá, jaký přístup použít. Všichni guru SQL, se kterými jsem mluvil, říkali zhruba totéž, že na výkonu ve skutečnosti nezáleží, protože SQL Server vytvoří zhruba stejné plány provedení. Jejich rada tedy zní, že použijete techniku, se kterou jste vy a váš tým nejpohodlnější. Stojí za to poznamenání, že po zadání této rady tito odborníci okamžitě vyjádří svou preferenci JOIN s před korelovanými poddotady.

Při vytváření vrstvy přístupu k datům pomocí typed dataSets fungují nástroje lépe při použití poddotazů. Průvodce objektem TableAdapter zejména automaticky nevygeneruje odpovídající INSERTpříkazy , UPDATEa , pokud DELETE hlavní dotaz obsahuje s JOIN , ale automaticky vygeneruje tyto příkazy při použití korelovaných poddotazů.

Pokud chcete tento nedostatek prozkoumat, vytvořte ve ~/App_Code/DAL složce dočasnou typed dataSet. V průvodci konfigurací tableadapter zvolte použití ad hoc příkazů SQL a zadejte následující SELECT dotaz (viz obrázek 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

Snímek obrazovky s oknem Průvodce konfigurací objektu TableAdaptor se zadaným dotazem, který obsahuje názvy JOINs

Obrázek 1: Zadejte hlavní dotaz, který obsahuje JOIN s (kliknutím zobrazíte obrázek v plné velikosti).

Ve výchozím nastavení objekt TableAdapter automaticky vytvoří INSERTpříkazy , UPDATEa DELETE na základě hlavního dotazu. Pokud kliknete na tlačítko Upřesnit, uvidíte, že je tato funkce povolená. Navzdory tomuto nastavení nebude objekt TableAdapter moct vytvořit INSERTpříkazy , UPDATEa DELETE , protože hlavní dotaz obsahuje JOIN.

Snímek obrazovky s oknem Upřesnit možnosti se zaškrtnutým políček Generovat příkazy Vložit, Aktualizovat a Odstranit

Obrázek 2: Zadání hlavního dotazu, který obsahuje JOIN s

Dokončete průvodce kliknutím na Dokončit. V tomto okamžiku bude Designer datová sada obsahovat jeden TableAdapter s dataTable se sloupci pro každé z polí vrácených v SELECT seznamu sloupců dotazu. To zahrnuje CategoryName a SupplierName, jak je znázorněno na obrázku 3.

Tabulka DataTable obsahuje sloupec pro každé pole vrácené v seznamu sloupců.

Obrázek 3: DataTable obsahuje sloupec pro každé pole vrácené v seznamu sloupců.

Zatímco DataTable má odpovídající sloupce, tableAdapter nemá hodnoty pro své InsertCommandvlastnosti , UpdateCommanda DeleteCommand . Potvrďte to tak, že v Designer kliknete na TableAdapter a přejdete na okno Vlastnosti. Uvidíte, že InsertCommandvlastnosti , UpdateCommanda DeleteCommand jsou nastavené na hodnotu (Žádné) .

Vlastnosti InsertCommand, UpdateCommand a DeleteCommand jsou nastaveny na hodnotu (None).

Obrázek 4: InsertCommandVlastnosti , UpdateCommanda DeleteCommand jsou nastavené na (Žádné) (Kliknutím zobrazíte obrázek v plné velikosti)

Pokud chcete tento nedostatek obejít, můžeme ručně poskytnout příkazy a parametry SQL pro InsertCommandvlastnosti , UpdateCommanda DeleteCommand prostřednictvím okno Vlastnosti. Alternativně bychom mohli začít konfigurací hlavního dotazu TableAdapter tak, aby neobsažoval žádné JOIN s. To nám umožní INSERTautomaticky vygenerovat příkazy , UPDATEa DELETE . Po dokončení průvodce můžeme ručně aktualizovat objekty TableAdapter SelectCommand z okno Vlastnosti tak, aby zahrnovaly syntaxiJOIN.

I když tento přístup funguje, při použití ad hoc dotazů SQL je velmi křehký, protože pokaždé, když se hlavní dotaz TableAdapter znovu nakonfiguruje prostřednictvím průvodce, automaticky generované INSERTpříkazy , UPDATEa DELETE se znovu vytvoří. To znamená, že všechna přizpůsobení, která jsme později provedli, by byla ztracena, pokud bychom pravým tlačítkem myši klikli na objekt TableAdapter, v místní nabídce vybrali Konfigurovat a průvodce znovu dokončili.

Křižnost automaticky generovaných INSERTpříkazů TableAdapter , UPDATE, a DELETE je naštěstí omezená na ad hoc příkazy SQL. Pokud váš objekt TableAdapter používá uložené procedury, můžete upravit SelectCommanduložené procedury , UpdateCommandInsertCommand, nebo DeleteCommand a znovu spustit průvodce konfigurací objektu TableAdapter, aniž byste se museli obávat, že se uložené procedury změní.

V následujících několika krocích vytvoříme objekt TableAdapter, který zpočátku používá hlavní dotaz, který vynechá všechny JOIN s, aby se automaticky vygenerovaly odpovídající uložené procedury vložení, aktualizace a odstranění. Potom aktualizujeme SelectCommand tak, aby se používal objekt JOIN , který vrací další sloupce ze souvisejících tabulek. Nakonec vytvoříme odpovídající třídu vrstvy obchodní logiky a předvedeme použití objektu TableAdapter na ASP.NET webové stránce.

Krok 1: Vytvoření objektu TableAdapter pomocí zjednodušeného hlavního dotazu

Pro účely tohoto kurzu přidáme objekt TableAdapter a dataTable silného Employees typu pro tabulku v NorthwindWithSprocs datové sadě. Tabulka Employees obsahuje ReportsTo pole, které zadalo EmployeeID hodnotu manažera zaměstnance. Například zaměstnankyně Anne Dodsworthová má ReportTo hodnotu 5, což je EmployeeID hodnota Stevena Buchanana. V důsledku toho se Anne hlásí Stevenovi, svému manažerovi. Kromě vykazování hodnoty jednotlivých zaměstnanců ReportsTo můžeme také chtít načíst jméno jejich nadřízený. Toho lze dosáhnout pomocí .JOIN Použití objektu JOIN při počátečním vytváření objektu TableAdapter však průvodci zabrání v automatickém generování odpovídajících funkcí vložení, aktualizace a odstranění. Proto začneme vytvořením objektu TableAdapter, jehož hlavní dotaz neobsahuje žádné JOIN s. Potom v kroku 2 aktualizujeme uloženou proceduru hlavního dotazu tak, aby načetla jméno nadřízený prostřednictvím JOIN.

Začněte otevřením NorthwindWithSprocs datové sady ve ~/App_Code/DAL složce . Klikněte pravým tlačítkem na Designer, v místní nabídce vyberte možnost Přidat a vyberte položku nabídky TableAdapter. Tím spustíte průvodce konfigurací tableAdapter. Jak je znázorněno na obrázku 5, nechte průvodce vytvořit nové uložené procedury a klikněte na Další. Chcete-li si osvěžit vytváření nových uložených procedur z průvodce TableAdapter, podívejte se na vytváření nových uložených procedur pro typed dataset s TableAdapter kurz.

Vyberte možnost Vytvořit nové uložené procedury.

Obrázek 5: Výběr možnosti Vytvořit nové uložené procedury (kliknutím zobrazíte obrázek v plné velikosti)

Pro hlavní dotaz TableAdapter použijte následující SELECT příkaz:

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

Vzhledem k tomu, že tento dotaz neobsahuje žádné JOIN s, průvodce objektem TableAdapter automaticky vytvoří uložené procedury s odpovídajícími INSERTpříkazy , UPDATEa DELETE a také uloženou proceduru pro spuštění hlavního dotazu.

Následující krok nám umožňuje pojmenovat uložené procedury TableAdapter. Použijte názvy Employees_Select, , Employees_InsertEmployees_Updatea Employees_Delete, jak je znázorněno na obrázku 6.

Pojmenování uložených procedur tableAdapter

Obrázek 6: Pojmenování uložených procedur tableAdapter (kliknutím zobrazíte obrázek v plné velikosti)

Poslední krok nás vyzve k pojmenování metod TableAdapter s. Jako názvy metod použijte Fill a GetEmployees . Nezapomeňte také ponechat zaškrtnuté políčko Create methods to send updates directly to the database (GenerateDBDirectMethods) (Vytvořit metody pro odesílání aktualizací přímo do databáze).

Pojmenujte metody TableAdapter s Fill a GetEmployees.

Obrázek 7: Pojmenujte metody Fill TableAdapter a GetEmployees (Kliknutím zobrazíte obrázek v plné velikosti)

Po dokončení průvodce se chvíli podívejte na uložené procedury v databázi. Měli byste vidět čtyři nové: Employees_Select, Employees_Insert, Employees_Updatea Employees_Delete. Dále zkontrolujte EmployeesDataTable a EmployeesTableAdapter právě vytvořené. Tabulka DataTable obsahuje sloupec pro každé pole vrácené hlavním dotazem. Klikněte na TableAdapter a přejděte na okno Vlastnosti. Uvidíte, že InsertCommandvlastnosti , UpdateCommanda DeleteCommand jsou správně nakonfigurované tak, aby volaly odpovídající uložené procedury.

Objekt TableAdapter zahrnuje možnosti vložení, aktualizace a odstranění.

Obrázek 8: Objekt TableAdapter zahrnuje možnosti vložení, aktualizace a odstranění (kliknutím zobrazíte obrázek v plné velikosti)

Po automatickém vytváření uložených procedur vkládání, aktualizací a odstraňování uložených procedur a InsertCommandsprávně nakonfigurovaných vlastností , UpdateCommanda DeleteCommand jsme připraveni přizpůsobit uloženou proceduru SelectCommand s tak, aby vracela další informace o každém manažerovi zaměstnanců. Konkrétně musíme aktualizovat uloženou proceduru Employees_Select tak, aby používala JOIN a vrátila hodnoty a správce LastNameFirstName. Po aktualizaci uložené procedury budeme muset aktualizovat tabulku DataTable tak, aby obsahovala tyto další sloupce. Tyto dva úkoly se budeme zabývat v krocích 2 a 3.

Krok 2: Přizpůsobení uložené procedury tak, aby zahrnovalaJOIN

Začněte tím, že přejdete do Průzkumníka serveru, přejdete do složky Uložené procedury databáze Northwind a otevřete uloženou proceduru Employees_Select . Pokud tuto uloženou proceduru nevidíte, klikněte pravým tlačítkem na složku Uložené procedury a zvolte Aktualizovat. Aktualizujte uloženou proceduru tak, aby k vrácení jména a příjmení nadřízenýho používala LEFT JOIN :

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 aktualizaci SELECT příkazu uložte změny tak, že přejdete do nabídky Soubor a zvolíte Uložit Employees_Select. Případně můžete kliknout na ikonu Uložit na panelu nástrojů nebo stisknout Ctrl+S. Po uložení změn klikněte pravým tlačítkem na uloženou proceduru Employees_Select v Průzkumníku serveru a zvolte Spustit. Tím se spustí uložená procedura a její výsledky se zobrazí v okně Výstup (viz obrázek 9).

V okně Výstup se zobrazí výsledky uložených procedur.

Obrázek 9: Výsledky uložených procedur se zobrazí v okně Výstup (kliknutím zobrazíte obrázek v plné velikosti)

Krok 3: Aktualizace sloupců DataTable s

V tomto okamžiku uložená procedura Employees_Select vrátí hodnoty aManagerLastName, ale chybí EmployeesDataTable tyto ManagerFirstName sloupce. Tyto chybějící sloupce je možné přidat do tabulky DataTable jedním ze dvou způsobů:

  • Ručně – klikněte pravým tlačítkem na tabulku DataTable v Designer DataSet a v nabídce Přidat zvolte Sloupec. Potom můžete sloupec pojmenovat a odpovídajícím způsobem nastavit jeho vlastnosti.
  • Automaticky – Průvodce konfigurací nástroje TableAdapter aktualizuje sloupce DataTable tak, aby odrážely pole vrácená uloženou procedurou SelectCommand . Při použití ad hoc příkazů SQL průvodce také odebere InsertCommandvlastnosti , UpdateCommanda DeleteCommand , protože SelectCommand nyní obsahuje JOIN. Při použití uložených procedur ale tyto vlastnosti příkazu zůstanou nedotčené.

V předchozích kurzech jsme prozkoumali ruční přidávání sloupců DataTable, včetně použití hlavního nebo podrobného seznamu hlavních záznamů s odrážkami s datovým seznamem podrobností a nahrávání souborů, a v dalším kurzu se na tento proces podíváme podrobněji. Pro účely tohoto kurzu však použijeme automatický přístup prostřednictvím průvodce konfigurací objektu TableAdapter.

Začněte tak, že na ni EmployeesTableAdapter kliknete pravým tlačítkem a v místní nabídce vyberete Konfigurovat. Tím se zobrazí průvodce konfigurace nástroje TableAdapter, který obsahuje seznam uložených procedur používaných k výběru, vložení, aktualizaci a odstraňování a jejich návratových hodnot a parametrů (pokud existují). Tento průvodce je znázorněný na obrázku 10. Tady vidíme, že uložená procedura Employees_Select teď vrací ManagerFirstName pole a ManagerLastName .

Průvodce zobrazí seznam aktualizovaných sloupců pro uloženou proceduru Employees_Select.

Obrázek 10: Průvodce zobrazuje aktualizovaný seznam sloupců pro uloženou proceduru Employees_Select (kliknutím zobrazíte obrázek v plné velikosti)

Dokončete průvodce kliknutím na Dokončit. Po návratu do Designer EmployeesDataTable dataset obsahuje dva další sloupce: ManagerFirstName a ManagerLastName.

Tabulka EmployeesDataTable obsahuje dva nové sloupce.

Obrázek 11: Obsahuje EmployeesDataTable dva nové sloupce (kliknutím zobrazíte obrázek v plné velikosti)

Chcete-li ilustrovat, že aktualizovaná Employees_Select uložená procedura funguje a že funkce vkládání, aktualizace a odstraňování objektu TableAdapter jsou stále funkční, vytvořte webovou stránku, která uživatelům umožní zobrazit a odstranit zaměstnance. Než ale vytvoříme takovou stránku, musíme nejprve vytvořit novou třídu ve vrstvě obchodní logiky pro práci se zaměstnanci ze NorthwindWithSprocs sady DataSet. V kroku 4 vytvoříme EmployeesBLLWithSprocs třídu. V kroku 5 použijeme tuto třídu z ASP.NET stránky.

Krok 4: Implementace vrstvy obchodní logiky

Ve složce s názvem EmployeesBLLWithSprocs.csvytvořte nový soubor ~/App_Code/BLL třídy . Tato třída napodobuje sémantiku existující EmployeesBLL třídy, pouze tato nová třída poskytuje méně metod a používá NorthwindWithSprocs DataSet (místo Northwind DataSet). Do třídy EmployeesBLLWithSprocs přidejte následující kód.

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;
    }
}

Vlastnost EmployeesBLLWithSprocs třídy s Adapter vrátí instanci NorthwindWithSprocs datové sady s EmployeesTableAdapter. Používá se ve třídách s GetEmployees a DeleteEmployee metodách. Metoda GetEmployees volá odpovídající GetEmployees metodu EmployeesTableAdapter s, která vyvolá uloženou proceduru Employees_Select a naplní její výsledky v EmployeeDataTable. Metoda DeleteEmployee podobně volá metodu EmployeesTableAdapter s Delete , která vyvolá uloženou proceduru Employees_Delete .

Krok 5: Práce s daty v prezentační vrstvě

Po dokončení předmětu EmployeesBLLWithSprocs jsme připraveni pracovat s daty zaměstnanců prostřednictvím ASP.NET stránky. JOINs.aspx Otevřete stránku ve AdvancedDAL složce a přetáhněte objekt GridView z panelu nástrojů do Designer a nastavte jeho ID vlastnost na Employees. Dále z inteligentní značky GridView vytvořte vazbu mřížky na nový ovládací prvek ObjectDataSource s názvem EmployeesDataSource.

Nakonfigurujte ObjectDataSource tak, aby používal EmployeesBLLWithSprocs třídu, a na kartách SELECT a DELETE se ujistěte, že GetEmployees jsou v rozevíracích seznamech vybrané metody a DeleteEmployee . Kliknutím na Dokončit dokončete konfiguraci ObjectDataSource s.

Nakonfigurujte ObjectDataSource tak, aby používal třídu EmployeesBLLWithSprocs.

Obrázek 12: Konfigurace objektu ObjectDataSource pro použití EmployeesBLLWithSprocs třídy (kliknutím zobrazíte obrázek v plné velikosti)

Nechte ObjectDataSource používat metody GetEmployees a DeleteEmployee.

Obrázek 13: Nechte ObjektDataSource použít GetEmployees metody a DeleteEmployee (kliknutím zobrazíte obrázek v plné velikosti)

Visual Studio přidá BoundField do GridView pro každý sloupec EmployeesDataTable s. Odeberte všechna tato pole BoundFields s výjimkou Titlevlastností , FirstNameLastName, , ManagerFirstNamea ManagerLastName přejmenujte HeaderText vlastnosti pro poslední čtyři BoundFields na Příjmení, Jméno, Jméno manažera a Příjmení manažera.

Abychom uživatelům umožnili odstranit zaměstnance z této stránky, musíme udělat dvě věci. Nejprve požádejte Objekt GridView, aby poskytoval možnosti odstraňování zaškrtnutím možnosti Povolit odstranění z inteligentní značky. Za druhé změňte vlastnost ObjectDataSource s OldValuesParameterFormatString z hodnoty nastavené průvodcem ObjectDataSource (original_{0}) na výchozí hodnotu ({0}). Po provedení těchto změn by deklarativní značky GridView a ObjectDataSource měly vypadat přibližně takto:

<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>

Stránku otestujete tak, že ji navštívíte v prohlížeči. Jak ukazuje obrázek 14, na stránce se zobrazí seznam všech zaměstnanců a jeho nadřízených (za předpokladu, že ho mají).

Funkce JOIN v Employees_Select uložená procedura vrátí název správce.

Obrázek 14: Funkce JOIN v Employees_Select uložené proceduře vrátí jméno manažera (kliknutím zobrazíte obrázek v plné velikosti)

Kliknutím na tlačítko Odstranit se spustí pracovní postup odstranění, který vyvrcholí spuštěním Employees_Delete uložené procedury. Příkaz pokusu DELETE v uložené proceduře však selže kvůli porušení omezení cizího klíče (viz obrázek 15). Konkrétně každý zaměstnanec má v Orders tabulce jeden nebo více záznamů, což způsobuje selhání odstranění.

Odstranění zaměstnance s odpovídajícími objednávkami má za následek porušení omezení cizího klíče

Obrázek 15: Odstranění zaměstnance s odpovídajícími objednávkami způsobí porušení omezení cizího klíče (kliknutím zobrazíte obrázek v plné velikosti)

Pokud chcete povolit odstranění zaměstnance, můžete:

  • Aktualizujte omezení cizího klíče na kaskádové odstranění,
  • Ručně odstraňte záznamy z Orders tabulky pro zaměstnance, které chcete odstranit, nebo
  • Aktualizujte uloženou proceduru Employees_Delete tak, aby před odstraněním záznamu nejprve odstranila OrdersEmployees související záznamy z tabulky. Tuto techniku jsme probrali v kurzu Použití existujících uložených procedur pro objekty TableAdapter typed DataSet s .

Nechám to jako cvičení pro čtenáře.

Souhrn

Při práci s relačními databázemi je běžné, že dotazy získávají data z více souvisejících tabulek. Korelované poddotazy a JOIN poddotazy poskytují dvě různé techniky pro přístup k datům ze souvisejících tabulek v dotazu. V předchozích kurzech jsme nejčastěji používali korelované poddotazy, protože objekt TableAdapter nemůže automaticky generovat INSERTpříkazy , UPDATEa DELETE pro dotazy zahrnující JOIN s. I když tyto hodnoty lze zadat ručně, při použití ad hoc příkazů SQL se po dokončení průvodce konfigurací TableAdapter přepíšou všechna vlastní nastavení.

Objekty TableAdapter vytvořené pomocí uložených procedur naštěstí netrpí stejnou křehkostí jako objekty vytvořené pomocí ad hoc příkazů SQL. Proto je možné vytvořit objekt TableAdapter, jehož hlavní dotaz používá JOIN při použití uložených procedur objekt . V tomto kurzu jsme viděli, jak takový Objekt TableAdapter vytvořit. Začali jsme použitím JOINdotazu -less SELECT pro hlavní dotaz objektu TableAdapter, aby se automaticky vytvořily odpovídající uložené procedury pro vložení, aktualizaci a odstranění. Po dokončení počáteční konfigurace nástroje TableAdapter jsme rozšířili uloženou proceduru SelectCommand tak, aby používala JOIN , a znovu spustili průvodce konfigurací nástroje TableAdapter, abychom aktualizovali EmployeesDataTable sloupce s.

Opětovné spuštění průvodce konfigurací nástroje TableAdapter automaticky aktualizovalo EmployeesDataTable sloupce tak, aby odrážely datová pole vrácená uloženou procedurou Employees_Select . Případně bychom tyto sloupce mohli do tabulky DataTable přidat ručně. Ruční přidávání sloupců do tabulky DataTable prozkoumáme v dalším kurzu.

Šťastné programování!

O autorovi

Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho najít na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na http://ScottOnWriting.NETadrese .

Zvláštní poděkování

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty tohoto kurzu byli Hilton Geisenow, David Suru a Teresa Murphy. Chcete si projít moje nadcházející články na WEBU MSDN? Pokud ano, dejte mi čáru na mitchell@4GuysFromRolla.comadresu .