ADO.NET - Úvod do databází v prostředí .NET Jan Kupka 2. května 2005
Obsah 1 Úvod do ADO.NET 1.1 Co je to ADO.NET? . . . . . . . . 1.2 Pro koho je tato příručka určena? . 1.3 Co budete potřebovat? . . . . . . . 1.4 Databáze . . . . . . . . . . . . . . 1.4.1 SQL Server . . . . . . . . . 1.4.2 MSDE . . . . . . . . . . . . 1.4.3 Oracle . . . . . . . . . . . . 1.4.4 MySQL . . . . . . . . . . . 1.4.5 Microsoft Access . . . . . . 1.4.6 Ostatní databázové systémy
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
3 3 3 3 4 4 4 4 5 5 5
2 Technologie ADO.NET 2.1 Připojení k databázi . . . . . . . . . . . . . . . . . . . 2.2 Využití vlastností platformy .NET . . . . . . . . . . . 2.3 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Zprostředkovatelé přístupu k databázovým systémům
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
6 6 6 6 7
3 Architektura ADO.NET 3.1 Jmenné prostory . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Přehled tříd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8 8 8
4 Třídy pro správu dat 4.1 DataSet . . . . . . . . . . . 4.2 DataTable . . . . . . . . . . 4.2.1 Události DataTable . 4.3 DataColumn . . . . . . . . 4.3.1 Vlastnosti sloupců . 4.4 DataRow . . . . . . . . . . 4.4.1 Constraints . . . . . 4.5 DataRelation . . . . . . . . 4.6 DataColumnMapping a DataTableMapping . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . .
9 9 9 10 10 10 11 11 12
. . . . . . . . . . . . . . . . . . . . .
12
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
5 Třídy pro připojení k databázi 5.1 Připojení k databázi (SqlConnection) . . . . . . . . . . . 5.2 Provádění SQL dotazů (SqlCommand) . . . . . . . . . . . 5.3 Datový adaptér (SqlDataAdapter) 5.3.1 Aktualizace dat v databázi 5.4 Tvorba příkazů (SqlCommandBuilder) . . . . . . . 5.5 Snímač dat (SqlDataReader) . . .
1
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
13 . . . . . . . . . . . . . . . . .
13
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14 16 16
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17 17
ADO.NET 5.6
Obsah
Transakce (SqlTransaction) . . . . . . . . . . . . . . . . . . . . .
18
6 XML
19
7 Visual Studio .NET 7.1 Připojení k databázi (SqlConnection) . . . . . . . . . . . 7.2 Provádění SQL dotazů (SqlCommand) . . . . . . . . . . . 7.3 Datový adaptér (SqlDataAdapter) 7.4 DataSet . . . . . . . . . . . . . . . 7.5 DataView . . . . . . . . . . . . . . 7.6 DataGrid . . . . . . . . . . . . . .
20 . . . . . . . . . . . . . . . . .
20
. . . . .
21 21 22 22 22
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
8 Závěr A Úvod do MSDE A.1 Instalace MSDE A.2 Práce s MSDE . A.3 Příprava základní A.4 Správa MSDE . .
23
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . databáze aneb rychlokurz . . . . . . . . . . . . . . .
2
. . . . . . SQL . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
24 24 24 24 25
Kapitola 1
Úvod do ADO.NET Vítám Vás při čtení příručky ADO.NET - Úvod do databází v prostředí .NET. Tato příručka si klade za cíl vás seznámit s přístupem k databázím v prostředí .NET firmy Microsoft. Databáze hrají v dnešním počítačovém světě stále důležitější roli v profesionálním i amatérském využití. Stejně tak si své místo pod Sluncem snaží dobýt prostředí .NET. Díky podpoře Microsoftu a nasazení v budoucích operačních systémech je jeho úspěch jistý. A pokud spojíte .NET s databázemi, dostanete ADO.NET, o kterém pojednává tato příručka. V této příručce se nachází mnoho ukázkových příkladů jednotlivých komponent ADO.NET. Kompletní ukázkové příklady by však zabraly mnoho místa a proto jsou v této příručce pouze podstatné části programů. Pokud by jste měli zájem o kompletní příklady, tak je naleznete na stránce http://adonet.kvalitne.cz. Problematika databází v prostředí ADO.NET je natolik rozsáhlá, že by kompletní publikace o ADO.NET zabrala tisíce stránek. Tato příručka by vám pouze měla zjednodušit start a nasměrovat vás pro další samostatné bádání. Díky neuvěřitelnému tempu, jakým byla publikace napsána, se v ní téměř jistě vyskytnou chyby a nepřesnosti. Budu tedy velmi rád, když mi jakékoliv vaše připomínky, výhrady a postřehy pošlete na mojí mailovou adresu:
[email protected].
1.1
Co je to ADO.NET?
Ze všeho nejdříve bychom si měli říci, co je vlastně ADO.NET, o kterém je celá tato příručka napsána. ADO.NET je rozsáhlou knihovnou tříd, které nám umožňují pracovat s databázemi a datovými soubory. Jelikož se jedná o součást .NET frameworku, poskytuje ADO.NET uživateli veškeré vymoženosti, které obsahuje samotný .NET. Jde zejména o podporu mnoha jazyků (C# , Managed C++, Visual Basic .NET, J# a dalších), automatické uvolňování paměti a objektově orientovaný přístup.
1.2
Pro koho je tato příručka určena?
Tato příručka je určena všem programátorům, kteří mají zkušenosti s programováním v jazyce C# . Samozřejmostí je znalost platformy .NET. Dále je doporučena znalost přístupu k databázovým systémům na programátorské úrovni v libovolném programovacím jazyce.
1.3
Co budete potřebovat?
Pro práci s ADO.NET budete samozřejmě potřebovat .NET Framework SDK. Své programy můžete psát v libovolném textovém editoru a posléze interpretovat 3
ADO.NET
Kapitola 1
pomocí řádkového interpretu, který je přiložen k .NET Framework SDK. Pro komfortnější práci ovšem doporučuji Microsoft Visual Studio .NET. Dále budete potřebovat databázový systém. Můžete používat jakýkoliv databázový systém podle vašeho osobního vkusu a podle toho, kolik peněz do systému můžete investovat. Pokud žádný databázový systém nepoužíváte, podívejte se do přílohy A a tam naleznete popis instalace a spuštění databázového systému MSDE. V příloze A rovněž naleznete postup vytvoření jednoduché databáze pro systém MSDE, která je v knize použita k předvádění práce s třídami ADO.NET.
1.4
Databáze
Pomocí rozhraní ADO.NET můžete připojit k programu libovolný databázový systém. Požadavkem je pouze to, aby systém měl vlastní OleDb ovladač. Tento ovladač naleznete prakticky u všech databázových systémů. V následujících odstavcích si přiblížíme nejpoužívanější databázové systémy.
1.4.1
SQL Server
SQL Server je databázový systém firmy Microsoft, což mu v ADO.NET dává určitý náskok před ostatními. Je pro něj připraveno vylepšené rozhraní, které mu umožňuje v některých případech dosahovat lepších výsledků než u ostatních systémů. Jeho nevýhodou je však vysoká cena. V současné době je nejnovější verzí Microsoft SQL Server 2000. Produkt je k dispozici ve třech základních verzích : Enterprise, Standard, Workgroup. Dalšími verzemi Microsoft SQL Serveru jsou například verze pro vývojáře nebo pro operační systém Windows CE. Firma Microsoft v současnosti dokončuje novou verzi SQL serveru - Microsoft SQL Server 2005. Internetové stránky programu: http://www.microsoft.com/sql/.
1.4.2
MSDE
MSDE není vlastně samostatný produkt. Je to jedna z verzí programu Microsoft SQL Serveru. Nespornou výhodou této verze je to, že je k dispozici zdarma. Je výhodná pro domácí použití, stejně jako pro vývojáře aplikací. MSDE je distribuována bez administrátorských nástrojů. Na internetu se dá ovšem sehnat mnoho vynikajících administrátorských nástrojů pro tento databázový systém, např. MSDE Manager nebo DBA Manager 2000. Dalším omezením je maximální počet pěti současně spuštěných procesů. Každý další proces musí počkat na skončení některého běžícího. Připojení k MSDE z programu je stejné jako u SQL Serveru, takže v případě, že už vám možnosti MSDE přestanou stačit, můžete bez problémů přejít na placený SQL Server. Společně s komerční verzí produktu Microsoft SQL Server 2005 by měla vyjít i nekomerční verze - Microsoft SQL Server 2005 Express, která bude nástupcem MSDE. Podle vyjádření pracovníků firmy Microsoft by měla být tato omezená verze pro vývojáře a domácí uživatele dostupná zdarma či za cenu distribučních nákladů. Internetové stránky programu: http://www.microsoft.com/sql/ /msde/.
1.4.3
Oracle
Oracle je přímým konkurentem SQL Serveru na poli databázových systémů. Firma Oracle v současné době nabízí svůj produkt Oracle ve verzi 10. Jedná se, stejně jako u SQL Serveru, o placený produkt. Existuje ovšem i jeho nekomerční verze, kterou je možné si po zaregistrování stáhnout z webových stránek firmy. Internetové stránky programu: http://www.oracle.com/.
4
ADO.NET
1.4.4
Kapitola 1
MySQL
MySQL je nejpopulárnější open-source databázový systém. Velkou výhodou je hlavně jeho multiplatformní použití, může být nasazen na operačních systémech Unix, Linux, Solaris, OS/2 i Windows. Protože je tento systém zdarma, nepodporuje některé funkce, které komerční systémy poskytují. Internetové stránky programu: http://www.mysql.com/.
1.4.5
Microsoft Access
Program, který je součástí balíku Microsoft Office firmy Microsoft a dá se použít pro tvorbu jednoduchých jednouživatelských databází. Pro jednoduchý systém či seznámení s databázemi tento program postačuje, ale osobně bych doporučil přeci jen raději některý z výše uvedených programů. Internetové stránky programu: http://office.microsoft.com/.
1.4.6
Ostatní databázové systémy
Prostřednictvím rozhraní ADO.NET můžete připojit k programu i další databázové servery. Výše uvedené programy však na poli databázových serverů představují absolutní špičku, a proto nebudou jiné databázové systémy v této příručce zmíněny.
5
Kapitola 2
Technologie ADO.NET V této kapitole se podíváme na ADO.NET trochu podrobněji. Zjistíme, jak ADO.NET pracuje, a co nového přináší v přístupu k databázím.
2.1
Připojení k databázi
Doba, kdy byly databáze uloženy na stejném počítači, ze kterého byly programem načítány, je stejně jako ukládání databází do jednoho souboru definitivně pryč. V dnešním světě potřebuje uživatel přistupovat k databázi z libovolného místa v internetu. Tento požadavek se samozřejmě musel promítnout do přístupu k databázím. V minulosti, kdy byla databáze umístěna na stejném počítači jako aplikace přistupující k ní, mohl být udržován přístup k databází po celou dobu běhu programu a nikomu to nevadilo. V dnešní době už tento postup není vhodný, neboť k databázi mohou přistupovat naráz tisíce uživatelů, což by okamžitě vedlo k omezení funkčnosti systému. Dalším důvodem je nespolehlivost síťového spojení, které může často padat, což by mělo za následek neustálé znovupřipojování k databázi. Z těchto důvodů vývojáři ve firmě Microsoft napsali ADO.NET tak, aby spojení s databází bylo navázáno pouze po dobu zpracování dotazu. Tento přístup s sebou ovšem také přináší některé problémy. Jedním z nich je například udržení konzistence dat v paměti a v databázovém systému.
2.2
Využití vlastností platformy .NET
ADO.NET je součástí .NET framework, což přináší mnoho výhod. Uveďme například objektově orientované programování, automatickou správu paměti či rozsáhlý systém vyjímek. Z tohoto plyne také použití libovolného jazyka obsahujícího podporu platformy .NET.
2.3
XML
Jazyk XML (eXtensible Markup Language) je často označován jako revoluční technologie. Je to hlavně díky jeho otevřenosti a jazykové nezávislosti. XML má podporu už v .NET Framework, ale ADO.NET jde ještě dál. Jazyk XML se stal stěžejním jazykem pro přenos dat v prostředí ADO.NET.
6
ADO.NET
2.4
Kapitola 2
Zprostředkovatelé přístupu k databázovým systémům
Jak už jsem napsal výše, tak ADO.NET umožňuje připojení k libovolnému databázovému systému, pro nějž existují OleDb ovladače. Nebyl by to ale Microsoft, kdyby pro svůj produkt nevytvořil něco extra. Pokud tedy používáte databázový systém Microsoft SQL Server (případně MSDE), můžete používat speciální datové typy, které byly vytvořeny speciálně pro tento databázový systém. Pro přístup k databázovému systému Microsoft SQL Server (případně free verzi MSDE) je vytvořen zprostředkovatel SqlClient (jmenný prostor System.Data.SqlClient) a pro přístup k ostatním databázím (Oracle, MySQL, atd.) je zde zprostředkovatel OleDb (jmenný prostor System.Data.OleDb). Zprostředkovatel SqlClient je kompletně napsaný v řízeném kódu a při připojení k databázi se snaží využívat co nejmenší počet vrstev, což by mu ve většině případů mělo pomoci k dosažení větší rychlosti přístupu než je tomu u zprostředkovatele OleDb.
7
Kapitola 3
Architektura ADO.NET 3.1
Jmenné prostory
Jmenné prostory, které musíte do svých programů zahrnout (pomocí syntaxe using), aby váš program mohl pracovat s databázemi: System.Data - jmenný prostor pro všechny obecné třídy a rozhraní pro přístup k datům v ADO.NET System.Data.Common - třídy sdílené zprostředkovateli dat System.Data.OleDb - třídy zprostředkovatele OleDb System.Data.SqlClient -třídy zprostředkovatele SQL Server System.Data.SqlTypes - datové typy aplikace SQL Server
3.2
Přehled tříd
Třídy v knihovně ADO.NET lze rozdělit na dvě množiny. První množinu tvoří třídy zaměřené na správu dat (Data Related Components). Tyto třídy jsou zcela nezávislé na databázi a reprezentují umístění dat z databáze v paměti. Druhou množinu tvoří třídy závislé na použité databázi (Data Provider Components). Tyto třídy umožňují propojení mezi třídami pro správu dat a databázovými systémy.
8
Kapitola 4
Třídy pro správu dat 4.1
DataSet
DataSet je základním stavebním prvkem každé složitější databázové aplikace. Jde o kompletní reprezentaci sady dat, která v sobě zahrnuje tabulky, vztahy mezi daty a omezení. S tím vším může DataSet pracovat v režimu offline (tedy odpojen od databázového systému). DataSet se nestará o připojení k databázi, jde pouze o objekt spravující data v paměti. DataSet může obsahovat data načtená nejen z databázových systémů, ale například i z xml souborů. K datům v DataSetu můžeme přistupovat, můžeme je upravovat, mazat nebo porovnávat s daty v původním datovém zdroji. Příklad vytvoření datasetu: DataSet dataset = new DataSet();
4.2
DataTable
DataTable (datová tabulka) ukládá data stejně jako to dělá tabulka v databázi. Data jsou umístěna v řádcích (rows) a každá položka v řádce přísluší konkrétnímu sloupci (column). Objekt DataTable může být používán samostatně, ale i jako součást objektu DataSet. DataTable se skládá z kolekce objektů Columns, kolekce objektů Rows a kolekce objektů Constraints. Kolekce Columns ve spojení s kolekcí Constraints definuje takzvané schéma objektu DataTable, zatímco kolekce Rows obsahuje data. Kolekce Columns Kolekce Columns je instancí třídy DataColumnCollection a jde o kontejner pro objekty typu DataColumn. Objekt DataColumn definuje sloupec datové tabulky včetně jeho jména, datového typu a informace o tom, zda jde o primární klíč či se jedná o autoinkrementační sloupec. Kolekce Rows Kolekce Rows je instancí třídy DataRowCollection a jde o kontejner pro objekty typu DataRow. Objekt DataRow obsahuje uložená data objektu DataTable podle jejich definic v kolekci DataTable.Columns. Každá řádka DataRow obsahuje jednu položku pro každý sloupec DataColumn v kolekci Columns.
9
ADO.NET
Kapitola 4
Kolekce Constraints Kolekce Constraints je instancí třídy ConstraintCollection a jde o kontejner pro objekty typu ForeignKeyConstraint a/nebo objekty typu UniqueConstraint. Objekt ForeignKeyConstraint definuje akci, která má být provedena na sloupec primárního nebo cizího klíče, pokud je řádek změněn nebo smazán. Objekt UniqueConstraint je používán k zajištění jedinečnosti všech hodnot ve sloupci. Příklad ručního vytvoření tabulky a její přidání do DataSetu: DataTable filmovaTabulka = new DataTable("Filmy"); DataSet ds = new DataSet(); ds.Tables.Add(filmovaTabulka);
4.2.1
Události DataTable
Následující události mohou být zachyceny a zpracovány při práci s objektem DataTable: Přehled událostí RowChanging RowChanged RowDeleting RowDeleted ColumnChanging ColumnChanged
objektu DataTable nastane při změně hodnoty v řádce nastane po úspěšné změně řádky nastane při pokusu o smazání řádky nastane po úspěšném smazání řádky nastane při změně hodnoty ve sloupci nastane po změně hodnoty ve sloupci
Příklad obsluhy události: //registrace udalosti filmovaTabulka.ColumnChanging = new DataColumnChangeEventHandler(ColumnChangingHandler); // obsluzna metoda udalosti private void ColumnChangingHandler(object sender, DataColumnChangeEventArgs e) { // kod obsluhujici udalost }
4.3
DataColumn
Objekt DataColumn definuje sloupec a jeho datový typ. Příklad vytvoření dvou sloupců pro tabulku filmovaTabulka: filmovaTabulka.Columns.Add("nazev",Type.GetType ("System.String")); filmovaTabulka.Columns.Add("rok",Type.GetType ("System.Int32"));
4.3.1
Vlastnosti sloupců
Primary Key Databázová tabulka má obvykle definovaný sloupec (skupinu sloupců), které jedinečně identifikují každou řádku v tabulce. Takovémuto identifikátoru sloupce 10
ADO.NET
Kapitola 4
(skupiny sloupců) se říká primární klíč. Vytvoření primárního klíče nad jedním sloupcem tabulky: DataColumn[] key = new DataColumn[1]; key[0] = filmovaTabulka.Columns["nazev"]; filmovaTabulka.PrimaryKey = key; Vytvoření primárního klíče nad více sloupci tabulky: DataColumn[] key = new DataColumn[2]; key[0] = filmovaTabulka.Columns["nazev"]; key[1] = filmovaTabulka.Columns["rok"]; filmovaTabulka.PrimaryKey = key; Autoinkrementace Autoinkrementační sloupec můžete nastavit přímo v databázovém systému nebo podle následujícího příkladu: // povoleni autoinkrementace filmovaTabulka.Columns["ID"].AutoIncrement = true; // zacatek autoinkrementace filmovaTabulka.Columns["ID"].AutoIncrementSeed = 10; // krok pri autoinkrementaci filmovaTabulka.Columns["ID"].AutoIncrementStep= 10; Nastavení sloupce pouze pro čtení Pokud nechcete uživateli povolit zápis dat do sloupce, nastavte vlastnost Readonly na hodnotu true dle následujícího příkladu: filmovaTabulka.Columns["ID"].ReadOnly = true;
4.4
DataRow
Objekt DataRow obsahuje data pro jednu řádku datové tabulky. Příklad naplnění jednoho řádku tabulky filmovaTabulka: //pomocna radka DataRow tmp; //nastaveni schematu pomocne radky tmp = filmovaTabulka.NewRow(); //nastaveni hodnoty pro sloupec nazev tmp["nazev"] = "Antitrust"; //nastaveni hodnoty pro sloupec rok tmp["rok"] = 2001; //pridani pomocne radky do tabulky filmovaTabulka.Rows.Add(tmp);
4.4.1
Constraints
Relační databáze zajišťují integritu dat pomocí omezení (constraints). Tato omezení přesně definují, co se bude dít v případě, že data v souvisejícím sloupci či řádce jsou měněna. V ADO.NET existují dva druhy omezení: ForeignKeyConstraint a UniqueConstraint.
11
ADO.NET
Kapitola 4
ForeingnKeyConstraint Toto omezení specifikuje akce, které mají být provedeny, pokud je hodnota ve sloupci či sloupcích smazána nebo upravena. Tento typ omezení je určen pro použití ve vztahu k primárnímu/cizímu klíči. Pokud je hodnota v rodičovském sloupci změněna nebo smazána, ForeignKeyConstraint definuje, co bude sloupec potomka v dané situaci dělat. Akce k provedení jsou definovány ve vlastnostech ForeignKeyConstraint.DeleteRule nebo ForeignKeyConstraint.UpdateRule a mohou bý nastaveny na tyto hodnoty: Rule.Cascade - smaže nebo upraví řádky ve vztahu (implicitní akce) Rule.SetNull - nastaví hodnoty ve vztažných řádkách na DBNull Rule.SetDefault - nastaví hodnoty ve vztažných řádcích na hodnotu vlastnosti DefaultValue Rule.None - na vztažné řádky nebudou provedeny žádné akce UniqueConstraint Toto omezení zajišťuje unikátní hodnoty v celém sloupci. Pokud se pokusíme zadat stejnou hodnotu do dvou řádků sloupce s omezením UniqueConstraint, bude vyvolána vyjímka.
4.5
DataRelation
Objekt DataRelation umožňuje vytvořit vztah mezi dvěma objekty typu DataTable pomocí jejich dvou sloupců. Jedná se prakticky o programové vytvoření vztahu primární klíč - cizí klíč. Příklad vytvoření relace mezi sloupci dvou tabulek: DataColumn parentColumn; DataColumn childColumn; // inicializace sloupcu parentColumn = DataSet.Tables["Customers"]. Columns["CustID"]; childColumn=DataSet.Table["Orders"]. Columns["CustID"]; // vytvoreni relace DataRelation relationCustomersOrders = new DataRelation ("CustomersOrders", parentColumn, childColumn); // pridani relace Dataset.Relations.Add(relationCustomersOrders);
4.6
DataColumnMapping a DataTableMapping
Tyto objekty umožňují namapovat sloupcům tabulky nová jména pro jednodušší použití v databázových aplikacích.
12
Kapitola 5
Třídy pro připojení k databázi 5.1
Připojení k databázi (SqlConnection)
Abychom mohli pracovat s databázovým systémem, musíme s ním nejdříve navázat spojení. Po připojení k databázovému serveru můžeme přenášet data mezi databází a naší aplikací. Po ukončení přenosu dat musíme spojení s databázovým serverem zase ukončit. Pro připojení k databázi potřebujeme vytvořit tzv. připojovací řetězec, který obsahuje základní data o připojení. Základní parametry připojovacího řetězce server název databázového serveru uid (UserID) jméno uživatele pwd (Password) heslo uživatele database název databáze Příklad připojení k databázovému serveru:
1
// řetězec pro připojení k databázovému serveru string connString = "server=(local);uid=sa; pwd=heslo;database=Test;"; // vytvoření objektu typu SqlConnection SqlConnection conn = new SqlConnection(connString); //otevření připojení conn.Open(); // tady bude nějaká práce s databázovým serverem //uzavření spojení conn.Close(); Druhý příklad ukazuje, jak se můžeme připojit k databázovému serveru pomocí syntaxe using. Při ukončení bloku uzavřeného příkazem using bude uzavřeno spojení s databází a zrušen objekt SqlConnection. Z tohoto důvodu nemusíme použít metodu Close(). 1 nezapomeňte
připojit k programu jmenný prostor System.Data.SqlClient
13
ADO.NET
Kapitola 5
// řetězec pro připojení k databázovému serveru string connString = "server=(local);uid=sa; pwd=heslo; database=Test;"; using (SqlConnection conn = new SqlConnection (connString)) { //otevření připojení conn.Open(); // tady bude nějaká práce s databázovým serverem } Předcházející příklad připojení k databázovému serveru je upřednostňovaný. Existují i další strategie připojování k databázovému serveru (například pomocí bloku try/catch/finally), ale těmi se již nebudu v této příručce zabývat. Poznámka 1: Chtěl bych upozornit, že veškerá vaše komunikace s databázovým systémem by měla být uzavírána do try/catch/ /finally bloků. S ohledem na názornost příkladů v této příručce však blok try/catch/finally na následujících stránkách neuvidíte. Poznámka 2: Ve všech následujících příkladech už budu předpokládat úspěšné připojení a odpojení databáze a budu se soustředit na vysvětlování konkrétních problémů.
5.2
Provádění SQL dotazů (SqlCommand)
Objekt SqlCommand je používán pro spouštění dotazů na datovém zdroji. Rozeznáváme tři druhy dotazů: CommandType.Text - používá se pro textové zadání sql dotazu (implicitní nastavení) CommandType.TableDirect - používá se pro získání všech sloupců tabulky, jejíž jméno zadáme jako parametr CommandType.StoredProcedure - používá se pro volání uložených procedur Příkazy mohou být spouštěny čtyřmi různými způsoby : ExecuteNonQuery(), ExecuteReader(), ExecuteScalar() a ExecuteXml Reader(). Podrobněji se podíváme na první tři metody. Metoda ExecuteNonQuery() - provede příkaz a nevrací žádné výsledky - používá se pro spouštění editačních, vkládacích a odstraňovacích dotazů - vrací jedinou hodnotu, kterou je počet ovlivněných záznamů Příklad: // SQL dotaz string strCommand = "CREATE TABLE Filmy (nazev varchar, rok int)"; 14
ADO.NET
Kapitola 5
// vytvoření objektu SqlCommand SqlCommand command = new SqlCommand(strCommand, conn); // provedení dotazu command.ExecuteNonQuery(); // nastavíme nový SQL dotaz command.CommandText = "INSERT INTO Filmy values (’X-Files’,1998)"; // příkaz vrací počet ovlivněných řádků int pocet = command.ExecuteNonQuery(); Console.WriteLine("Pocet ovlivnenych radek: {0}", pocet); Poznámka: Mnohem zajímavější je vracení počtu ovlivněných záznamů například při příkazu UPDATE, v tomto případě jde pouze o demonstrační příklad. Metoda ExecuteReader() - provede příkaz a vrátí objekt, který implementuje rozhraní IDataReader - vrácený objekt můžeme procházet pomocí snímače dat (DataReader), který si podrobně popíšeme později Příklad: string strCommand = "SELECT nazev, rok FROM Filmy"; SqlCommand command = new SqlCommand(strCommand, conn); SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) { Console.WriteLine("{0} - {1}",reader[0], reader[1]); } Metoda ExecuteScalar() - provede příkaz a vrátí jednu hodnotu - používá se například pro určení počtu záznamů v tabulce Příklad: string strCommand = "SELECT COUNT(*) FROM Filmy"; SqlCommand command = new SqlCommand(strCommand, conn); // vrátí počet záznamů v tabulce Filmy int cislo = (int) command.ExecuteScalar(); Console.WriteLine(cislo.ToString());
15
ADO.NET
Kapitola 5
Uložené procedury Volání procedur provádíme taktéž pomocí objektu SqlCommand. Nejdříve musíme vytvořit proceduru v naší databázi. Zde je jednoduchý příklad uložené procedury pro SQL server: CREATE PROCEDURE InsertFilm(@nazev varchar(50), @rok INTEGER) AS INSERT INTO Filmy VALUES (@nazev, @rok); Příklad použití uložené procedury: // nastaveni objektu SqlCommand SqlCommand command = new SqlCommand("InsertFilm"); command.Connection = conn; command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter ("@nazev", SqlDbType.VarChar)); command.Parameters.Add(new SqlParameter ("@rok", SqlDbType.Int)); //spusteni ulozene procedury s parametry command.Parameters[0].Value="Dune"; command.Parameters[1].Value=1984; command.ExecuteNonQuery(); Poznámka: Tato procedura sice nemá hlubší smysl, neboť stejnou funkci splní jednoduchý SQL dotaz, ale pro ukázku postačí.
5.3
Datový adaptér (SqlDataAdapter)
Už víme, jak se připojit k databázi. Také víme, že data jsou uložena v objektu DataSet. Jak ale data přenést z databáze do objektu DataSet? K tomuto účelu slouží objekt DataAdapter. DataAdapter tvoří imaginární most mezi daty v paměti (DataSet) a mezi daty v databázovém systému. Příklad načtení dat do objektu DataSet: DataSet ds = new DataSet(); SqlDataAdapter da = new SqlDataAdapter ("SELECT * FROM Filmy;", conn); //naplnění datasetu da.Fill(ds,"Filmy"); //výpis názvu sloupců v tabulce Filmy v datasetu foreach (DataColumn sloupec in ds.Tables["Filmy"]. Columns) { Console.WriteLine(sloupec.Caption.ToString()); }
5.3.1
Aktualizace dat v databázi
Pokud zavoláme metodu Fill datového adaptéru (DataAdapter), tak jsou data v objektu DataSet obnovena novými daty z databáze. Co ale budeme dělat v případě, že byla změněna data v DataSetu a chceme je nahrát zpět do databáze? V takovém případě máme dvě možnosti. 16
ADO.NET
Kapitola 5
První možností je zachytávání stavů DataSetu a vytvoření vlastních SQL dotazů jako reakce na změnu jeho stavu. Každý řádek v DataSetu má vlastní hodnotu RowState, která je při načtení dat z databáze nastavena na Unchanged (nezměněn). Pokud do DataSetu přidáme nový řádek, je jeho vlastnost RowState nastavena na Added (přidán). Smazanému řádku 2 je nastavena hodnota Deleted (smazán). Upravenému řádku je nastavena hodnota Modified (změněn). Aktualizace SQL dotazy je často nahrazována uloženými procedurami. Druhou možností, jak postupovat v případě, že chceme změněná data v DataSetu přenést do databázového systému je použití objektu SqlCommandBuilder, o kterém si povíme v následující kapitole.
5.4
Tvorba příkazů (SqlCommandBuilder)
SqlCommandBuilder je objekt, který nám usnadňuje práci při přenosu změněných dat z objektu DataSet zpátky do databázového systému. SqlCommandBuilder provede analýzu příkazu SELECT v datovém adaptéru a následně pomocí něj vygeneruje SQL dotazy INSERT, UPDATE a DELETE. Pro použití objektu SqlCommandBuilder musíme splnit následující podmínky: 1. Datový adaptér musí mít definován příkaz SELECT. Ten můžeme nastavit buď v konstruktoru objektu DataAdapter nebo pomocí vlastnosti SelectCommand datového adaptéru. 2. V příkazu SELECT musí být zadán sloupec primárního klíče nebo sloupec s omezením unique. Příklad použití objektu SqlCommandBuilder pro aktualizaci dat v databázi: DataSet ds = new DataSet(); SqlDataAdapter da = new SqlDataAdapter ("SELECT * FROM Filmy;", conn); // SqlCommandBuilder připojený na datový adaptér SqlCommandBuilder cb = new SqlCommandBuilder(da); //naplnění datasetu da.Fill(ds,"Filmy"); //přidání nového záznamu do datasetu DataRow myRow; myRow = ds.Tables["Filmy"].NewRow(); myRow[0] = "XXX"; myRow[1] = 2000; ds.Tables["Filmy"].Rows.Add(myRow); // update dat v databázi da.Update(ds, "Filmy");
5.5
Snímač dat (SqlDataReader)
Objekt SqlDataReader reprezentuje nejjednodušší přístup k datům v databázi. Jeho jednoduchost je však vykoupena několika nevýhodami. DataReader může 2 Řádek
není fyzicky vymazán, jen je mu nastaven příznak a není zobrazován
17
ADO.NET
Kapitola 5
pracovat pouze s připojenou databází, tzn. že je potřebné kvalitní připojení k databázi. DataReader může v jednom okamžiku pracovat pouze s jednou řádkou v databázi. K výhodám naopak patří, že DataReader ke své činnosti nevyžaduje DataSet, data mohou být například vypisována na monitor nebo zpracovávána jiným způsobem. DataReader si můžeme představit jako jednosměrný databázový kurzor. Příklad použití objektu DataReader: // příkaz pro DataReader SqlCommand command = new SqlCommand ("SELECT * FROM Filmy",conn); //spuštění příkazu SqlDataReader reader = command.ExecuteReader(); //načítání a výpis dat while (reader.Read()) { Console.WriteLine("{0} - {1}", reader.GetValue(0), reader.GetValue(1)); } //ukončení čtení reader.Close();
5.6
Transakce (SqlTransaction)
Transakce jsou používány v případě, že chceme spustit více příkazů najednou, které mají být provedeny jako jedna nedělitelná transakce. Příklad provedení tří příkazů najednou: // začátek transakce SqlTransaction trans = conn.BeginTransaction(); // nastavení objektu SqlCommand SqlCommand command = conn.CreateCommand(); command.Connection=conn; command.Transaction=trans; command.CommandText = "INSERT INTO Filmy VALUES (’American Pie’,1999)"; command.CommandText = "INSERT INTO Filmy VALUES (’American Pie 2’,2001)"; command.ExecuteNonQuery(); command.CommandText = "INSERT INTO Filmy VALUES (’American Pie 3’,2004)"; command.ExecuteNonQuery(); // potvrzení transakce trans.Commit();
18
Kapitola 6
XML Jak už jsem napsal dříve, XML je využíváno v ADO.NET při většině interních operací. V této kapitole si ukážeme pouze základní operace, kterými je načtení dat ze souboru typu XML do objektu DataSet a uložení objektu DataSet do XML souboru. XML poskytuje mnoho dalších zajímavých záležitostí, např. pomocí schémat dokumentu XML (XSD) vám může program automaticky vygenerovat zdrojový kód ve vašem programovacím jazyce, který vytvoří tabulky dle schématu. Bohužel toto téma již přesahuje rámec této příručky. Uložení databáze do souboru XML Pokud máme v paměti vytvořený objekt DataSet, můžeme ho jednoduše uložit do XML souboru. Buď můžeme do XML souboru uložit pouze data, nebo může být v souboru ještě uvedeno schéma DataSetu. Uložení bez schématu provedeme příkazem (ds je instance objektu DataSet): ds.WriteXml("data.xml"); Uložení včetně schématu provedeme příkazem: ds.WriteXml("data2.xml", XmlWriteMode.WriteSchema); Vytvoření databáze ze souboru XML Načtení dat do DataSetu z XML souboru je velice jednoduché. Stačí napsat následující řádky: DataSet ds = new DataSet(); ds.ReadXml("data.xml"); Je úplně jedno, zda XML soubor obsahuje schéma či nikoliv. V případě, že jsou v souboru pouze data, tak si strukturu objekt DataSet vytvoří sám podle uspořádání těchto dat.
19
Kapitola 7
Visual Studio .NET V této kapitole se podíváme na to, jak nám ulehčuje přístup k databázím programovací prostředí Visual Studio .NET. Po spuštění aplikace Visual Studio a vytvoření nového projektu typu Windows Application naleznete po pravé straně pracovní plochy lištu ToolBox. Na ní se nachází paleta Data, která obsahuje komponenty pro práci s databázemi. Jsou to komponenty pro správu dat (DataSet a DataView) a komponenty pro přístup k databázím (Connection, Command a DataAdapter). Komponenty pro přístup k databázím existují v několika verzích - s předponou Sql (pro SQL Server a MSDE), OleDb (pro databázové systémy připojené pomocí ovladače OleDb), Odbc (pro databázové systémy připojené pomocí ovladače Odbc, což je předchůdce ovladače OleDb) a Oracle (speciální ovladač pro databázový systém Oracle). V dalším textu budu opět pracovat s databázovým systémem MSDE, a proto budou názvy objektů začínat předponou Sql.
7.1
Připojení k databázi (SqlConnection)
Připojení k databázi provedeme pomocí následujícího postupu. Nejdříve si vytvoříme připojení na náš databázový server. Nad lištou ToolBox se nachází lišta označená jako Server Explorer. Po jejím otevření vybereme položku Data Connections a klikneme na ní pravým tlačítkem. Vzápětí vybereme položku Add Connection. . .. Otevře se formulář, ve kterém postupně nastavíme připojení ke zvolené databázi. Jako název serveru můžeme napsat (local), což znamená, že se připojujeme k databázi běžící na tomto počítači, nebo adresu serveru s databází. Vyplníme kolonky Uživatelské jméno a Heslo a zašktneme políčko Povolit uložení hesla, abychom nemuseli tyto údaje zadávat při běhu programu. Nyní si můžeme vybrat pomocí rozbalovacího menu databázi, ke které se chceme připojit. Případně si můžeme spojení ještě otestovat kliknutím na tlačítko Testovat připojení. Po potvrzení voleb se nám pod položku Data Connections přidalo první připojení na databázi. Takovýchto připojení si můžeme vytvořit libovolné množství. Nespornou výhodou tohoto postupu je fakt, že Visual Studio má jednotlivá připojení trvale uložena, takže je můžete použít i pro vývoj dalších aplikací. Pokud je připojení nastaveno, můžeme připojit databázi k naší aplikaci. Pro připojení se používá komponenta SqlConnection.
20
ADO.NET
Kapitola 7
Důležité vlastnosti komponenty SqlConnection Name název komponenty ConnectionString připojovací řetězec můžete buď vybrat z menu, pokud jste si vytvořili připojení popsané v předcházejícím odstavci, nebo zadat ručně Database vrací název databáze DataSource vrací název instance SQL serveru ServerVersion vrací verzi instance SQL serveru, ke kterému jste připojeni WorkstationId vrací název klientské stanice Důležité metody komponenty SqlConnection Open() otevření spojení s databází Close() uzavření spojení s databází
7.2
Provádění SQL dotazů (SqlCommand)
Pro tvorbu SQL dotazu slouží ve Visual Studiu komponenta SqlCommand. Nejdůležitější vlastnosti komponenty SqlCommand Name název komponenty CommandText SQL dotaz CommandType nastavení typu dotazu (Text, StoredProcedure, TableDirect) Connection připojení k databázi (instance objektu SqlConnection) Nejdůležitější metody komponenty SqlCommand ExecuteNonQuery() provedení příkazu bez vrácení výsledku ExecuteScalar() provedení příkazu s návratem jedné hodnoty ExecuteReader() provedení příkazu s návratem objektu implementujícího rozhraní IDataReader
7.3
Datový adaptér (SqlDataAdapter)
Po přidání komponenty SqlDataAdapter na plochu formuláře se spustí průvodce, který nám pomůže s nastavením této komponenty. Po odklepnutí úvodního informačního okna přejdeme na další, ve kterém vybereme připojení (SqlConnection), které již máme vytvořeno, případně vytvoříme nové. Na další obrazovce musíme nastavit způsob aktualizace dat v databázi (pomocí SQL dotazů, vytvořením nových uložených procedur či použitím již existujících procedur). Pro jednoduchost zvolíme aktualizaci pomocí SQL dotazů (Use Sql Statements). Na další obrazovce můžeme pomocí aplikace Query Builder vytvořit SQL dotaz (typu SELECT) či ho zapsat ručně. Poslední obrazovka už jen informuje, zda se vše povedlo nebo ne. Ukázka kódu (naplnění objektu typu DataSetu pomocí objektu typu DataAdapter): sqlDataAdapter1.Fill(dataSet1);
21
ADO.NET
7.4
Kapitola 7
DataSet
DataSet opět nalezneme na paletě Data lišty ToolBox. Nejdůležitější Name DataSetName Relations Tables
vlastnosti komponenty DataSet název komponenty pojmenování instance DataSetu kolekce relací mezi tabulkami kolekce tabulek
Nejdůležitější metody komponenty DataSet AcceptChanges provedení změn RejectChanges odmítnutí změn ReadXml(string filename) načtení dat z XML do DataSetu WriteXml(string filename) uložení dat z DataSetu do XML
7.5
DataView
Komponentu DataView najdeme stejně jako předcházející komponenty na paletě Data. Tato komponenta nám umožňuje vybírat data z DataSetu podle různých filtrovacích dotazů. Nejdůležitější vlastnosti komponenty DataView Name název komponenty Table specifikuje tabulku, nad kterou vytvoříme pohled AllowDelete specifikuje možnost mazat data AllowEdit specifikuje možnost upravovat data AllowNew specifikuje možnost vytvářet data RowFilter filtr řádek (např.: rok=1998) RowStateFilter filtr stavu řádek (Unchanged, New, Deleted) Nejdůležitější metody komponenty DataView AddNew() přidání nové řádky Delete(int index) smazání řádky na zadaném indexu
7.6
DataGrid
DataGrid je jediná vizuální komponenta, kterou si v této příručce představíme. Komponentu nenalezneme na paletě Data, nýbrž na paletě Windows Forms. Jde o datovou tabulku, která reprezentuje data vizuálně stejným způsobem jako jsou data uložena v databázi. DataGrid může zobrazovat data uložená v komponentách DataSet nebo DataView. Nejdůležitější vlastnosti komponenty DataGrid Name název komponenty AllowSorting umožní řazení dat kliknutím na název sloupce, dle kterého chceme řadit DataMember zobrazení pouze vybrané tabulky DataSetu DataSource zdroj dat (DataSet nebo DataView) ReadOnly nastavení komponenty pouze pro čtení
22
Kapitola 8
Závěr ADO.NET je pravděpodobně nejefektivnější způsob přístupu k databázovým systémům současnosti. Pokud tedy umíte některý z programovacích jazyků podporovaných platformou .NET, nemůžete zvolit lépe. Přehled základní práce s databázovými systémy jsem se pokusil přiblížit v této příručce.
23
Příloha A
Úvod do MSDE A.1
Instalace MSDE
1. Databázový systém MSDE si můžete stáhnout zcela zdarma z následující adresy: http://www.microsoft.com/sql/msde/ downloads/download.asp. 2. Soubor MSDE2000A.exe je samorozbalovací archív, který si rozbalte do libovolného adresáře. 3. Nyní musíte spustit soubor setup.exe s parametry, které definují způsob instalace. Pokud se vám nechce pročítat nápovědu, spusťte soubor následujícím příkazem (pro základní použití zcela postačuje): setup.exe SAPWD=”heslo” SECURITYMODE=SQL. 4. Následuje tichá instalace programu. 5. Po skončení instalace a případném restartu systému již můžete přistupovat k databázovému serveru jako uživatel sa s heslem, které jste zadali ve třetím kroku. Běh MSDE indikuje ikonka databáze se zelenou šipkou v trayi.
A.2
Práce s MSDE
Systému MSDE můžete zadávat SQL dotazy pomocí konzolové aplikace. Tuto aplikaci najdete při standardní instalaci v adresáři C:\Program Files\Microsoft SQL Server\80\Tools\Binn. Program má název OSQL.exe a nejjednodušeji ho spustíte příkazem OSQL.exe -U username -P password, kde username je vaše uživatelské jméno a password je vaše heslo.
A.3
Příprava základní databáze aneb rychlokurz SQL
Po spuštění konzolové aplikace si nejdříve vytvoříme novou databázi. Zadáme příkaz create database Test a stiskneme klávesu Enter. 1 Program nám vypíše údaje o vytvoření databáze a jejího log souboru. Nyní se do databáze přepneme pomocí příkazu use Test. Vytvoříme jednoduchou tabulku pomocí SQL dotazu CREATE TABLE Filmy(nazev varchar(50) PRIMARY KEY, rok int);. 1 Připomínám, že MSDE je free verzí MS SQL Serveru, takže musíme po každém SQL dotazu zapsat ještě příkaz go a stisknout klávesu Enter.
24
ADO.NET
Příloha A
Pro tento příklad budeme předpokládat, že každý film má unikátní název. Do tabulky vložíme jeden záznam následujícím SQL dotazem: INSERT INTO Filmy VALUES(’X-Files’, 1998);. Dotazem SELECT * FROM Filmy; se přesvědčíme, že je naše testovací tabulka s daty vytvořena.
A.4
Správa MSDE
Ke spravování a konfiguraci databázového systému MSDE můžete využít různé programy, např. DbaMgR2k nebo MSDE Manager for .NET.
25
Literatura [1] Simon Robinson, K. Scott Allen, Ollie Cornes, Jay Glenn, Zach Greenvoss, Burton Harvey, Christian Nagel, Morgan Skinner, Karli Watson, 2003. C# Programujeme profesionálně, Wrox, Computer Press. [2] Dalibor Kačmář, 2001. Programujeme .NET aplikace ve Visual Studiu .NET, Computer Press. [3] Luboslav Lacko, 2003. SQL Hotová řešení, Computer Press.
26