Přidání dalších sloupců do tabulky DataTable (C#)
Při použití Průvodce objektem TableAdapter k vytvoření typové datové sady obsahuje odpovídající tabulka DataTable sloupce vrácené hlavním databázovým dotazem. Existují ale situace, kdy datatable musí obsahovat další sloupce. V tomto kurzu zjistíme, proč se doporučují uložené procedury, když potřebujeme další sloupce DataTable.
Úvod
Při přidávání objektu TableAdapter do typed DataSet je odpovídající schéma DataTable určena hlavním dotazem objektu TableAdapter. Pokud například hlavní dotaz vrátí datová pole A, B a C, bude mít dataTable tři odpovídající sloupce s názvy A, B a C. Kromě svého hlavního dotazu může objekt TableAdapter obsahovat další dotazy, které vrací podmnožinu dat na základě nějakého parametru. Kromě hlavního ProductsTableAdapter
dotazu, který vrací informace o všech produktech, obsahuje například také metody jako GetProductsByCategoryID(categoryID)
a GetProductByProductID(productID)
, které vracejí informace o konkrétním produktu na základě zadaného parametru.
Model schématu DataTable s odráží hlavní dotaz TableAdapter funguje dobře, pokud všechny metody TableAdapter vrací stejná nebo méně datových polí než ta, která jsou zadána v hlavním dotazu. Pokud metoda TableAdapter potřebuje vrátit další datová pole, měli bychom odpovídajícím způsobem rozšířit schéma DataTable. V kurzu Master/Detail Using a Bulleted List of Master Records with a Details DataList jsme přidali metodu , která vrátila CategoryID
datová pole , CategoryName
a Description
definovaná v hlavním dotazu plus NumberOfProducts
další datové pole, které hlásilo počet produktů přidružených k CategoriesTableAdapter
jednotlivým kategoriím. Ručně jsme do CategoriesDataTable
třídy přidali nový sloupec, abychom z této nové metody zachytili hodnotu datového NumberOfProducts
pole.
Jak je popsáno v kurzu Nahrávání souborů , je třeba věnovat velkou pozornost objektům TableAdapter, které používají ad hoc příkazy SQL a mají metody, jejichž datová pole přesně neodpovídají hlavnímu dotazu. Pokud je znovu spuštěn Průvodce konfigurací objektu TableAdapter, aktualizuje všechny metody TableAdapter tak, aby jejich seznam datových polí odpovídal hlavnímu dotazu. V důsledku toho se všechny metody s přizpůsobenými seznamy sloupců vrátí k seznamu sloupců hlavního dotazu a nevrátí očekávaná data. K tomuto problému nedochází při použití uložených procedur.
V tomto kurzu se podíváme na to, jak rozšířit schéma DataTable tak, aby zahrnovalo další sloupce. Vzhledem k křehkosti objektu TableAdapter při použití ad hoc příkazů SQL budeme v tomto kurzu používat uložené procedury. Další informace o konfiguraci objektu TableAdapter pro použití uložených procedur najdete v kurzu Vytváření nových uložených procedur pro typed DataSet s Objekty TableAdapter .
Krok 1: PřidáníPriceQuartile
sloupce doProductsDataTable
V kurzu Vytváření nových uložených procedur pro objekty TableAdapter typed DataSet jsme vytvořili typovou sadu dat s názvem NorthwindWithSprocs
. Tato datová sada aktuálně obsahuje dvě tabulky DataTable: ProductsDataTable
a EmployeesDataTable
. Má ProductsTableAdapter
následující tři metody:
GetProducts
– hlavní dotaz, který vrací všechny záznamy zProducts
tabulkyGetProductsByCategoryID(categoryID)
– vrátí všechny produkty se zadaným ID kategorie.GetProductByProductID(productID)
– vrátí konkrétní produkt se zadaným id produktu.
Hlavní dotaz a dvě další metody vrátí stejnou sadu datových polí, konkrétně všechny sloupce z Products
tabulky. Neexistují žádné korelované poddotazy ani JOIN
dotazy, které by přetahovaly související data z Categories
tabulek nebo Suppliers
. ProductsDataTable
Proto má odpovídající sloupec pro každé pole v tabulceProducts
.
Pro účely tohoto kurzu přidáme metodu s názvem GetProductsWithPriceQuartile
, ProductsTableAdapter
která vrátí všechny produkty. Kromě standardních datových polí produktu bude obsahovat PriceQuartile
také datové pole, GetProductsWithPriceQuartile
které určuje, pod který kvartil cena produktu spadá. Například produkty, jejichž ceny jsou v nejdražších 25 %, budou mít PriceQuartile
hodnotu 1, zatímco produkty, jejichž ceny spadají do nejnižších 25 %, budou mít hodnotu 4. Než se však začneme starat o vytvoření uložené procedury pro vrácení těchto informací, musíme nejprve aktualizovat ProductsDataTable
tak, aby zahrnoval sloupec pro uložení PriceQuartile
výsledků při GetProductsWithPriceQuartile
použití metody.
Otevřete datovou NorthwindWithSprocs
sadu a klikněte pravým tlačítkem na ProductsDataTable
. V místní nabídce zvolte Přidat a pak vyberte Sloupec.
Obrázek 1: Přidání nového sloupce do ProductsDataTable
(kliknutím zobrazíte obrázek v plné velikosti)
Tím se do tabulky DataTable přidá nový sloupec s názvem Column1 typu System.String
. Musíme aktualizovat název tohoto sloupce na PriceQuartile a jeho typ na System.Int32
, protože se použije k uložení čísla mezi 1 a 4. Vyberte nově přidaný sloupec v ProductsDataTable
a v okno Vlastnosti nastavte Name
vlastnost na PriceQuartile a DataType
vlastnost na System.Int32
.
Obrázek 2: Nastavení vlastností a DataType
nových sloupců Name
(kliknutím zobrazíte obrázek v plné velikosti)
Jak ukazuje obrázek 2, je možné nastavit další vlastnosti, například jestli hodnoty ve sloupci musí být jedinečné, jestli je sloupec automatickým přírůstkem, jestli jsou povolené hodnoty databáze NULL
atd. Tyto hodnoty nechte nastavené na výchozí hodnoty.
Krok 2: VytvořeníGetProductsWithPriceQuartile
metody
Teď, když jsme aktualizovali ProductsDataTable
PriceQuartile
sloupec , jsme připraveni vytvořit metodu GetProductsWithPriceQuartile
. Začněte tak, že kliknete pravým tlačítkem na objekt TableAdapter a v místní nabídce zvolíte Přidat dotaz. Tím se zobrazí průvodce konfigurace dotazu TableAdapter, který nás nejprve vyzve k tomu, jestli chceme použít ad hoc příkazy SQL nebo novou nebo existující uloženou proceduru. Vzhledem k tomu, že ještě nemáme uloženou proceduru, která vrací data o cenách kvartilu, umožníme, aby pro nás TableAdapter vytvořil tuto uloženou proceduru. Vyberte možnost Vytvořit novou uloženou proceduru a klikněte na Další.
Obrázek 3: Požádejte průvodce TableAdapter, aby vytvořil uloženou proceduru (kliknutím zobrazíte obrázek v plné velikosti).
Na následující obrazovce, znázorněné na obrázku 4, se průvodce zeptá, jaký typ dotazu přidat. Vzhledem k tomu, že GetProductsWithPriceQuartile
metoda vrátí všechny sloupce a záznamy z Products
tabulky, vyberte možnost VYBRAT, která vrací řádky a klikněte na Další.
Obrázek 4: Náš dotaz bude příkazem SELECT
, který vrátí více řádků (kliknutím zobrazíte obrázek v plné velikosti).
Dále se zobrazí výzva k zadání SELECT
dotazu. Do průvodce zadejte následující dotaz:
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
NTILE(4) OVER (ORDER BY UnitPrice DESC) as PriceQuartile
FROM Products
Výše uvedený dotaz používá novou NTILE
funkci SQL Server 2005 k rozdělení výsledků do čtyř skupin, kde jsou skupiny určeny hodnotami UnitPrice
seřazenými sestupně.
Tvůrce dotazů bohužel neví, jak analyzovat OVER
klíčové slovo, a při analýze výše uvedeného dotazu zobrazí chybu. Proto zadejte výše uvedený dotaz přímo do textového pole v průvodci bez použití Tvůrce dotazů.
Poznámka
Další informace o ntile a SQL Server 2005 s další funkce řazení naleznete v části ROW_NUMBER (Transact-SQL) a Ranking Functions z SQL Server 2005 Books Online.
Po zadání SELECT
dotazu a kliknutí na Další nás průvodce požádá o zadání názvu uložené procedury, která se vytvoří. Pojmenujte novou uloženou proceduru Products_SelectWithPriceQuartile
a klikněte na Další.
Obrázek 5: Pojmenování uložené procedury Products_SelectWithPriceQuartile
(kliknutím zobrazíte obrázek v plné velikosti)
Nakonec jsme vyzváni k pojmenování metod TableAdapter. Nechte zaškrtnutá políčka Fill a DataTable i Return a DataTable a pojmenujte metody FillWithPriceQuartile
a GetProductsWithPriceQuartile
.
Obrázek 6: Pojmenujte metody TableAdapter a klikněte na Dokončit (kliknutím zobrazíte obrázek v plné velikosti)
Se zadaným SELECT
dotazem a pojmenovanou uloženou procedurou a metodami TableAdapter dokončete průvodce kliknutím na Dokončit. V tomto okamžiku se může od průvodce zobrazit upozornění, že konstruktor OVER
nebo příkaz SQL není podporován. Tato upozornění lze ignorovat.
Po dokončení průvodce by objekt TableAdapter měl obsahovat FillWithPriceQuartile
metody a GetProductsWithPriceQuartile
a databáze by měla obsahovat uloženou proceduru s názvem Products_SelectWithPriceQuartile
. Chvíli se ujistěte, že Objekt TableAdapter skutečně obsahuje tuto novou metodu a že uložená procedura byla správně přidána do databáze. Pokud při kontrole databáze nevidíte uloženou proceduru, zkuste kliknout pravým tlačítkem na složku Uložené procedury a zvolit Aktualizovat.
Obrázek 7: Ověření přidání nové metody do třídy TableAdapter
Obrázek 8: Ujistěte se, že databáze obsahuje uloženou proceduru Products_SelectWithPriceQuartile
(kliknutím zobrazíte obrázek v plné velikosti)
Poznámka
Jednou z výhod použití uložených procedur místo příkazů SQL ad hoc je to, že opětovné spuštění průvodce konfigurací objektu TableAdapter nezmění seznamy sloupců uložených procedur. Ověřte to tak, že kliknete pravým tlačítkem na objekt TableAdapter, v místní nabídce zvolíte možnost Konfigurovat, aby se spustil průvodce, a kliknutím na Dokončit ho dokončete. Pak přejděte do databáze a prohlédněte si uloženou proceduru Products_SelectWithPriceQuartile
. Všimněte si, že jeho seznam sloupců nebyl změněn. Kdybychom používali příkazy SQL ad hoc, opětovné spuštění průvodce konfigurací tableadapter by vrátilo seznam sloupců dotazu tak, aby odpovídal hlavnímu seznamu sloupců dotazu, a tím by se příkaz NTILE odebral z dotazu používaného GetProductsWithPriceQuartile
metodou.
Při vyvolání metody Data Access Layer GetProductsWithPriceQuartile
tableAdapter spustí uloženou proceduru Products_SelectWithPriceQuartile
a přidá řádek do ProductsDataTable
třídy pro každý vrácený záznam. Datová pole vrácená uloženou procedurou se mapují na ProductsDataTable
sloupce s. Vzhledem k tomu, PriceQuartile
že se z uložené procedury vrátí datové pole, přiřadí se jeho hodnota sloupci ProductsDataTable
s PriceQuartile
.
Pro metody TableAdapter, jejichž dotazy nevrací PriceQuartile
datové pole, PriceQuartile
je hodnota sloupce s hodnota určená jeho DefaultValue
vlastností. Jak je znázorněno na obrázku 2, je tato hodnota nastavená na DBNull
výchozí hodnotu. Pokud dáváte přednost jiné výchozí hodnotě, jednoduše nastavte DefaultValue
vlastnost odpovídajícím způsobem. Jen se ujistěte, že DefaultValue
je hodnota platná vzhledem ke sloupci DataType
(tj. System.Int32
pro PriceQuartile
sloupec).
V tomto okamžiku jsme provedli nezbytné kroky pro přidání dalšího sloupce do tabulky DataTable. Pokud chcete ověřit, že tento další sloupec funguje podle očekávání, pojďme vytvořit stránku ASP.NET, která zobrazuje názvy, ceny a ceny jednotlivých produktů. Než to ale uděláme, musíme nejprve aktualizovat vrstvu obchodní logiky tak, aby zahrnovala metodu, která volá metodu DAL GetProductsWithPriceQuartile
s. V kroku 3 aktualizujeme BLL a pak vytvoříme ASP.NET stránku v kroku 4.
Krok 3: Rozšíření vrstvy obchodní logiky
Než použijeme novou GetProductsWithPriceQuartile
metodu z prezentační vrstvy, měli bychom nejprve přidat odpovídající metodu do BLL. ProductsBLLWithSprocs
Otevřete soubor třídy a přidejte následující kód:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public NorthwindWithSprocs.ProductsDataTable GetProductsWithPriceQuartile()
{
return Adapter.GetProductsWithPriceQuartile();
}
Stejně jako ostatní metody načítání dat v ProductsBLLWithSprocs
GetProductsWithPriceQuartile
systému metoda jednoduše zavolá odpovídající GetProductsWithPriceQuartile
metodu DAL a vrátí její výsledky.
Krok 4: Zobrazení informací o ceně kvartilu na webové stránce ASP.NET
Po dokončení přidání BLL jsme připraveni vytvořit ASP.NET stránku, která zobrazuje cenu kvartilu pro každý produkt. AddingColumns.aspx
Otevřete stránku ve AdvancedDAL
složce a přetáhněte Objekt GridView z panelu nástrojů do Designer nastavením jeho ID
vlastnosti na Products
. Z inteligentní značky GridView ji vytvořte vazbu na nový ObjectDataSource s názvem ProductsDataSource
. Nakonfigurujte ObjectDataSource tak, aby používal metodu ProductsBLLWithSprocs
třídy s GetProductsWithPriceQuartile
. Vzhledem k tomu, že se bude jednat o mřížku jen pro čtení, nastavte rozevírací seznamy na kartách UPDATE, INSERT a DELETE na (Žádné) .
Obrázek 9: Konfigurace objektu ObjectDataSource pro použití ProductsBLLWithSprocs
třídy (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 10: Načtení informací o produktu z GetProductsWithPriceQuartile
metody (kliknutím zobrazíte obrázek v plné velikosti)
Po dokončení průvodce Konfigurovat zdroj dat sada Visual Studio automaticky přidá BoundField nebo CheckBoxField do objektu GridView pro každé z datových polí vrácených metodou . Jedním z těchto datových polí je PriceQuartile
, což je sloupec, který jsme přidali do ProductsDataTable
pole v kroku 1.
Upravte pole GridView a odeberte všechna ProductName
pole kromě , UnitPrice
a PriceQuartile
BoundFields. UnitPrice
Nakonfigurujte BoundField tak, aby se jeho hodnota formátovala jako měna a aby byly UnitPrice
PriceQuartile
hodnoty BoundField zarovnané doprava a na střed. Nakonec aktualizujte zbývající vlastnosti BoundFields HeaderText
na Product( Produkt), Price (Cena) a Price Quartil (Cena kvartil). Zaškrtněte také políčko Enable Sorting (Povolit řazení) z inteligentní značky GridView.
Po těchto úpravách by deklarativní značky GridView a ObjectDataSource měly vypadat takto:
<asp:GridView ID="Products" runat="server" AllowSorting="True"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSource">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="PriceQuartile" HeaderText="Price Quartile"
SortExpression="PriceQuartile">
<ItemStyle HorizontalAlign="Center" />
</asp:BoundField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsWithPriceQuartile"
TypeName="ProductsBLLWithSprocs">
</asp:ObjectDataSource>
Obrázek 11 ukazuje tuto stránku při návštěvě prostřednictvím prohlížeče. Všimněte si, že na začátku jsou produkty seřazené podle ceny v sestupném pořadí, přičemž každému produktu je přiřazena odpovídající PriceQuartile
hodnota. Tato data se samozřejmě dají řadit podle jiných kritérií, přičemž hodnota sloupce Price Quartil (Cena kvartil) stále odráží pořadí produktů s ohledem na cenu (viz Obrázek 12).
Obrázek 11: Produkty jsou objednány podle jejich cen (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 12: Produkty jsou seřazené podle jejich názvů (kliknutím zobrazíte obrázek v plné velikosti)
Poznámka
Pomocí několika řádků kódu bychom mohli rozšířit GridView tak, aby zbarvil řádky produktu na základě jejich PriceQuartile
hodnoty. Můžeme tyto výrobky v prvním kvartilu obarvit světle zeleně, v druhém kvartilu světle žlutou a tak dále. Doporučujeme, abyste si na chvíli tuto funkci přidali. Pokud potřebujete opakovat formátování objektu GridView, projděte si kurz Vlastní formátování založené na datech .
Alternativní přístup – Vytvoření dalšího objektu TableAdapter
Jak jsme viděli v tomto kurzu, při přidávání metody do objektu TableAdapter, která vrací jiná datová pole než ta, která jsou napsaná hlavním dotazem, můžeme do tabulky DataTable přidat odpovídající sloupce. Takový přístup však funguje dobře pouze v případě, že v objektu TableAdapter existuje malý počet metod, které vrací různá datová pole, a pokud se tato alternativní datová pole příliš neliší od hlavního dotazu.
Místo přidávání sloupců do DataTable můžete místo toho přidat další objekt TableAdapter do datové sady, který obsahuje metody z prvního objektu TableAdapter, které vracejí různá datová pole. Pro účely tohoto kurzu jsme místo přidání PriceQuartile
sloupce do objektu ProductsDataTable
(kde ho GetProductsWithPriceQuartile
používá pouze metoda), mohli jsme do datové sady ProductsWithPriceQuartileTableAdapter
přidat další objekt TableAdapter, který jako hlavní dotaz použil uloženou Products_SelectWithPriceQuartile
proceduru. ASP.NET stránky, které potřebovaly získat informace o produktu s cenovým kvartilem ProductsWithPriceQuartileTableAdapter
, by používaly , zatímco stránky, které nebyly, mohly dál používat ProductsTableAdapter
.
Přidáním nového objektu TableAdapter zůstanou tabulky DataTables nepřipravené a jejich sloupce přesně zrcadlí datová pole vrácená jejich metodami TableAdapter. Další doplňky TableAdapter ale můžou zavádět opakující se úlohy a funkce. Pokud například tyto ASP.NET stránky, které zobrazovaly PriceQuartile
sloupec, potřebovaly také podporu vložení, aktualizace a odstranění, ProductsWithPriceQuartileTableAdapter
musí mít objekt správně nakonfigurované vlastnosti InsertCommand
, UpdateCommand
a DeleteCommand
. I když by tyto vlastnosti zrcadlily ProductsTableAdapter
s, tato konfigurace zavádí další krok. Kromě toho teď existují dva způsoby, jak aktualizovat, odstranit nebo přidat produkt do databáze – prostřednictvím ProductsTableAdapter
tříd a ProductsWithPriceQuartileTableAdapter
.
Soubor ke stažení pro tento kurz obsahuje ProductsWithPriceQuartileTableAdapter
třídu v NorthwindWithSprocs
datové sadě, která tento alternativní přístup ilustruje.
Souhrn
Ve většině scénářů vrátí všechny metody v objektu TableAdapter stejnou sadu datových polí, ale existují situace, kdy konkrétní metoda nebo dvě mohou potřebovat vrátit další pole. Například v kurzu Master/Detail Using a Bulleted List of Master Records with a Details DataList jsme přidali metodu , která kromě datových polí hlavního dotazu vrátila NumberOfProducts
pole, které hlásilo počet produktů přidružených k CategoriesTableAdapter
jednotlivým kategoriím. V tomto kurzu jsme se podívali na přidání metody, ProductsTableAdapter
která vrátila PriceQuartile
pole kromě datových polí hlavního dotazu. Pokud chcete zachytit další datová pole vrácená metodami TableAdapter, musíme do tabulky DataTable přidat odpovídající sloupce.
Pokud plánujete ručně přidávat sloupce do tabulky DataTable, doporučujeme, aby metoda TableAdapter používala uložené procedury. Pokud objekt TableAdapter používá ad hoc příkazy SQL, při každém spuštění průvodce konfigurací objektu TableAdapter se všechny seznamy datových polí metod vrátí k datovým polím vráceným hlavním dotazem. Tento problém se nevztahuje na uložené procedury, a proto se doporučují a v tomto kurzu se používaly.
Všechno nejlepší na 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 zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.
Zvláštní poděkování
Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty pro tento kurz byli Randy Schmidt, Jacky Goor, Bernadette Leigh a Hilton Giesenow. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.