5. diel - SqlDataReader a pripojené databázy v C # .NET
V minulej lekcii, Pripojená databázová aplikácia v C # .NET , sme sa pripojili k databáze a vypísali počet riadkov v tabuľke. V dnešnom C# .NET tutoriálu sa naučíme čítať z databázy jednotlivé riadky.
Spracovanie dát
Ak potrebujete spustiť nad databázou dotaz, ktorý vracia viac záznamov
(ten vyššie vracal len jedno číslo), musíte na spracovanie výsledku
otázky využiť triedu *DataReader
. Inštanciu tejto triedy ako
výsledok vráti metóda ExecuteReader()
triedy
Command
. Trieda *DataReader
umožňuje prechádzať
výslednú množinu dát po jednotlivých záznamoch. K tomu slúži metóda
Read()
. Prístup k jednotlivým atribútom záznamu môžete
získať pomocou indexu alebo názvu stĺpca uvedeného v hranatých
zátvorkách, prípadne pomocou metód Get...()
, ktoré vám
hodnoty rovno prevedú na požadovaný dátový typ.
Príklad 4
Vypíšte na obrazovku všetky slovíčka. U slovíčok budeme chcieť
vypísať stĺpce: Id
, Czech
a
English
.
Riešenie
SqlCommand prikaz = new SqlCommand("SELECT Id, Czech, English FROM Word", pripojeni); pripojeni.Open(); SqlDataReader dataReader = prikaz.ExecuteReader(); while (dataReader.Read()) // dokud neprojdeme vsechny zaznamy { Console.WriteLine("{0} {1} {2}", dataReader[0], // index sloupce (Id) dataReader["Czech"], // nazev sloupce dataReader.GetString(2)); // index sloupce (English) s prevedenim na pozadovany datovy typ }
výsledok:
SQL dotaz miesto COUNT
teraz vymenováva stĺpcov, ktoré
vyberáme. Reader číta riadok po riadku čo databázy vrátila a výsledky
vypisuje do konzoly.
Odovzdávanie parametrov
Urobme z aplikácie naozajstný slovníček a nechajme používateľa zadať slovíčko, ktoré mu následne preložíme.
Sql injekcie
Najprv si ukážme, ako sa to nemá robiť. Naivne by sme si mohli nechať zadať slovíčko a to potom priamo vložiť ako vyhľadávanou frázu do dotazu. Zdrojový kód aplikácie by vyzeral takto:
// tento zdrojový kód je nebezpečný string connectionString = @"Data Source=localhost\MSSQLSERVER2008;Initial Catalog=SlovnicekDB;Integrated Security=True"; using (SqlConnection pripojeni = new SqlConnection(connectionString)) { pripojeni.Open(); Console.WriteLine("Zadej anglické slovíčko k překladu"); string slovo = Console.ReadLine(); SqlCommand prikaz = new SqlCommand("SELECT Czech FROM Word WHERE English='" + slovo + "'", pripojeni); SqlDataReader dataReader = prikaz.ExecuteReader(); while (dataReader.Read()) // dokud neprojdeme vsechny zaznamy { Console.WriteLine("Překlad: {0}", dataReader["Czech"]); } } Console.ReadKey();
SQL dotaz je podobný tomu predchádzajúcemu. Nezaujímajú nás však už
všetky riadky, ale len tie, kde má stĺpec English
určitú
hodnotu. Podmienku v SQL zapíšeme pomocou klauzuly WHERE
.
Hoci sa zdá, že aplikácia funguje korektne:
Zamyslite sa nad tým, čo sa stane, keď nejaký používateľ zadá na preklad tento reťazec:
'; DROP TABLE Word --
Škodlivý kód sa nám vloží priamo do dotazu a spustí sa nad databázou. Útočníkovi tak dávame plnú kontrolu and našimi dátami, v tomto prípade nám nenávratne vymaže celú tabuľku. To je ešte pomerne nevinný útok, mohol by nám zobrať aj heslá používateľov a podobne.
Odovzdávanie parametrov
Bezpečnostný problém spôsobuje samozrejme priame vkladanie hodnôt do textu SQL dotazu. Útok sa preto nazýva SQL injection, ako vloženie cudzieho SQL kódu do nášho. Platí zásada, že musíme počítať s tým, že škodlivý kód môže byť v každom parametri, ktorý do dotazu vkladáme. Nemožno sa spoľahnúť na to, že táto premenné asi nebude nič od užívateľa obsahovať. Aplikácia sa mení a do premennej by sa mohla časom dostať aj napríklad len časť hodnoty, ktorú zadal používateľ. A verte mi, že užívatelia sú vynaliezaví a budú vašu aplikáciu skúšať a budú vám tam tieto hodnoty vkladať.
V minulosti sa parametre ošetrovali špeciálnou funkciou, ktorá tzv. Zescapovala škodlivé znaky. Moderné otázky sa píšu pomocou tzv. Prepared Statements. Tie fungujú tak, že sa do dopytu namiesto parametrov vloží len špeciálne značky. Parametre sa potom odovzdávajú oddelene. Ukážme si, ako do dotazu vložiť parametre správne:
string connectionString = @"Data Source=localhost\MSSQLSERVER2008;Initial Catalog=SlovnicekDB;Integrated Security=True"; using (SqlConnection pripojeni = new SqlConnection(connectionString)) { pripojeni.Open(); Console.WriteLine("Zadej anglické slovíčko k překladu"); string slovo = Console.ReadLine(); SqlCommand prikaz = new SqlCommand("SELECT Czech FROM Word WHERE English=@slovo", pripojeni); prikaz.Parameters.AddWithValue("@slovo", slovo); SqlDataReader dataReader = prikaz.ExecuteReader(); while (dataReader.Read()) // dokud neprojdeme vsechny zaznamy { Console.WriteLine("Překlad: {0}", dataReader["Czech"]); } } Console.ReadKey();
Všimnite si, že v SQL dotaze je len zástupná značka, ktorá sa označuje
zavináčom a ľubovoľným názvom. Nepíšeme okolo nej a apostrof, tie sú
dodané neskôr podľa typu značky. Pred zavolaním metódy
ExecuteReader()
do dotazu pripojíme parametre, v našom prípade
parameter @slovo
, ktorého hodnotou bude premenná slovo. Databáza
si sama parametre ošetrí a nemusíme sa báť, že by nám aplikácii niekto
mohol nabúrať.
V budúcej lekcii, Databázy v C # .NET - INSERT, UPDATE, DELETE a COUNT , si ukážeme, ako záznamy v databáze pridávať, mazať a editovať. Zdrojové kódy dnešného programu sú ako vždy v prílohe k stiahnutiu.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 450x (1.03 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#