Grafikus C# – Windows Forms tanfolyam › 3.7 lecke Windows Forms · 3.7 lecke · biztonság és pontosság A paraméterek nem csak a biztonságot szolgálják: pontosabbá is teszik a programot. A 3.3 leckében megtanultad, hogy a felhasználó szövege soha nem kerülhet az SQL szövegébe. Most a gyakorlati részleteket nézzük meg: milyen típusú értéket adj át, hogyan tárolj és keress dátumot, mit tegyél a Paraméterezett lekérdezések és SQL-biztonság – típusok, dátumok, LIKE és IN
LIKE speciális karaktereivel, hogyan szűrj több városra egyszerre, és mit mutass a felhasználónak hiba esetén.
A lecke végére
- érted, mit nyersz a paraméterekkel a biztonságon kívül (pontosság, aposztróf, tizedesvessző);
- a számot előbb számmá alakítod (
TryParse), és számként adod át; - a dátumot ISO formátumban (
yyyy-MM-dd) tárolod és hasonlítod; - a
LIKEspeciális karaktereit (%,_) azESCAPEsegítségével védi; - változó hosszúságú
INlistát építesz paraméterekkel; - a hibaüzenetet biztonságosan kezeled: a felhasználónak általános üzenet, a naplóba a részletek.
Mielőtt elkezded
Ehhez a leckéhez kell a 3.3 lecke (paraméterezett lekérdezés), a 3.5 lecke (LIKE, BETWEEN, IN) és az 1.3 lecke (TryParse).
A paraméter több, mint védelem
Az összefűzött SQL nem csak biztonsági kockázat, hanem pontatlan is. Három gyakori ok:
| Probléma | Összefűzéssel | Paraméterrel |
|---|---|---|
| Aposztróf a szövegben (O'Hara) | Az SQL szintaktikailag hibás lesz. | Hibátlan, a szöveg csak adat. |
Tizedesvessző a számban (4,5) | Az SQL 4,5 két külön értéknek látja, hiba lesz. | A szám típusú érték nem szövegként utazik. |
| Idézőjelek, speciális karakterek | Meg kell védeni őket kézzel, könnyű elfelejteni. | Nincs védeni való, az érték külön utazik. |
Jósolj!
A txtAr mezőbe 4,5 kerül, és a program összefűzi: "... WHERE ar >= " + txtAr.Text. Mi lesz az SQL szövege, és mit csinál az adatbázis?
Jóslat ellenőrzése
Az SQL szövege ... WHERE ar >= 4,5 lesz. Az SQL-ben a vessző elválasztó jel, a tizedesjel pedig a pont, ezért az adatbázis szintaktikai hibát jelez. A paraméterezett változatnál a program előbb számmá alakítja a szöveget (double.TryParse), és a szám típusú értéket adja át, a tizedesjel kérdése eltűnik. Mellékesen: az összefűzés a felhasználó beírt szövegét is bevitte volna az SQL-be, ami a 3.3 leckében látott biztonsági kockázatot hordozza.
Típusok: számot számként, szöveget szövegként
Az AddWithValue az átadott C# érték típusából következtet az adatbázis típusára. Ha egy számot szövegként adsz át, a program működhet (az SQLite sokat megenged), de a viselkedés kiszámíthatatlanabb lesz. A jó szokás: előbb alakítsd át a bevitelt a kívánt típusra, ellenőrizd, és csak utána add át.
// ROSSZ: a szöveget közvetlenül átadjuk
parancs.Parameters.AddWithValue("@ar", txtAr.Text);
// JÓ: előbb számmá alakítjuk és ellenőrizzük
int maxAr;
if (!int.TryParse(txtAr.Text, out maxAr) || maxAr < 0)
{
Uzenet("Az ár nemnegatív egész szám legyen!", true);
return;
}
parancs.Parameters.AddWithValue("@ar", maxAr);
// még pontosabb: a típust is megadjuk
parancs.Parameters.Add("@ar", System.Data.DbType.Int32).Value = maxAr;Int32, String, Double, DateTime). Hosszabb, de nincs kétség a típus felől.DBNull.Value az egyértelmű választás (3.6 lecke).Dátumok az SQLite-ban
Az SQLite-nak nincs önálló dátumtípusa: a dátumot szövegként, számként vagy időbélyegként tárolhatod. A legegyszerűbb és legbiztonságosabb megoldás a szöveges ISO formátum: yyyy-MM-dd (például 2026-06-06). Ennek két nagy előnye van: (1) a szövegesen rendezett sorrend megegyezik az időrenddel, (2) a BETWEEN pontosan működik. A magyar 2026. 06. 06. vagy a 06.06.2026 formátum szövegként rendezve rossz sorrendet ad.
Készítsünk egy kis táblát az események gyakorlásához (DB Browser, Execute SQL, majd Ctrl+S):
CREATE TABLE esemenyek (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nev TEXT NOT NULL,
datum TEXT NOT NULL, -- ISO formátum: yyyy-MM-dd
ar INTEGER NOT NULL DEFAULT 0
);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Tavaszi kirándulás', '2026-04-18', 2500);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Színházi est', '2026-05-09', 4200);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Sportnap', '2026-05-23', 0);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Bál: 100% jókedv', '2026-06-06', 3000);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Nyári tábor', '2026-07-13', 45000);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Tanévnyitó', '2026-09-01', 0);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Szülői értekezlet', '2026-09-15', 0);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Karácsonyi vásár', '2026-12-12', 1500);
INSERT INTO esemenyek (nev, datum, ar) VALUES ('Farsang_2027', '2027-02-06', 1800);A C# programban a DateTimePicker értékét ugyanilyen szöveggé alakítjuk a paraméter átadásakor. A CultureInfo.InvariantCulture gondoskodik róla, hogy a formátum a gép nyelvi beállításától függetlenül mindig azonos legyen:
private static string IsoDatum(DateTime datum)
{
return datum.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
}
public static DataTable Esemenyek(string nevresz, DateTime tol, DateTime ig, int maxAr)
{
string sql = "SELECT id, nev, datum, ar FROM esemenyek "
+ "WHERE nev LIKE @minta ESCAPE '^' "
+ "AND datum BETWEEN @tol AND @ig "
+ "AND ar <= @maxar ORDER BY datum";
DataTable tabla = new DataTable();
using (SQLiteConnection kapcsolat = UjKapcsolat())
{
kapcsolat.Open();
using (SQLiteCommand parancs = new SQLiteCommand(sql, kapcsolat))
{
parancs.Parameters.AddWithValue("@minta", "%" + LikeVedelem(nevresz) + "%");
parancs.Parameters.AddWithValue("@tol", IsoDatum(tol));
parancs.Parameters.AddWithValue("@ig", IsoDatum(ig));
parancs.Parameters.AddWithValue("@maxar", maxAr);
using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(parancs))
{
adapter.Fill(tabla);
}
}
}
return tabla;
}Jósolj!
A datum BETWEEN '2026-05-01' AND '2026-06-06' szűrés szerepel-e a június 6-i Bál és a május 23-i Sportnap? Milyen eredményt kapnál, ha a dátumokat 2026.06.06. formában tárolnád?
Jóslat ellenőrzése
Mindkettő szerepel, mert a BETWEEN a határokat is tartalmazza, és az ISO szövegek ábécé szerinti sorrendje megegyezik az időrenddel. A 2026.06.06. formátumnál a szöveges összehasonlítás karakterenként dolgozik, így a hónap és a nap sorrendje, a ponttal és a szóközökkel együtt, megbízhatatlan eredményt adhat. Mivel az SQLite szöveggé alakítva hasonlít, a dátumot mindig nagyságrendi sorrendben (év, hónap, nap) tárold.
Ha az időpont is benne van
Ha a szövegben az óra is szerepel (2026-06-06 18:30), akkor a BETWEEN '2026-06-06' AND '2026-06-06' kihagyja az aznapi eseményt, mert a 2026-06-06 18:30 hosszabb szöveg, és a végső határnál nagyobb. Ilyenkor a végdátum helyett a következő nap kezdetét használd, és < jelet: datum >= @tol AND datum < @kovetkezoNap.
A LIKE speciális karakterei és az ESCAPE
A paraméterezett LIKE védett az SQL-befecskendezés ellen, de még mindig van egy buktató: ha a felhasználó % vagy _ jelet ír a keresőmezőbe, az a mintában speciális karakter marad. A % bármit, a _ pontosan egy karaktert jelent. Egy 100% keresés így az összes eseményt visszaadná. Az ESCAPE kulcsszóval megadhatsz egy védőkaraktert: az utána álló jelet szó szerint kell érteni.
// a ^ lesz a védőkarakter: a ^% jelentése szó szerint a % jel
private static string LikeVedelem(string szoveg)
{
return szoveg.Replace("^", "^^").Replace("%", "^%").Replace("_", "^_");
}
// az SQL-ben: WHERE nev LIKE @minta ESCAPE '^'^ a védőkarakter a mintában.% jel elé védőkarakter kerül, így szó szerinti százalékjelet jelent.LIKE minta szabályait az adatbázis értelmezi, ezért a minta speciális karaktereit külön kell védeni.Jósolj!
A felhasználó a _ jelet írja a keresőmezőbe, és a program a LikeVedelem nélkül, ESCAPE nélkül keres. Melyik események jönnek vissza a feladat adataiból? Mit ad a védett keresés?
Jóslat ellenőrzése
Védelem nélkül a minta %_%, vagyis „legalább egy karakter”, ezért mind a kilenc esemény megjelenik. A védett keresésnél a minta %^_%: szó szerinti alsó vonást keres, ezért csak a Farsang_2027 esemény jön vissza.
Változó hosszúságú IN lista
Ha több városra szeretnél szűrni (IN ('Győr', 'Pécs')), a lista hossza változik attól függően, hány várost jelöl a felhasználó. A teljes listát nem adhatod át egyetlen paraméterként. A megoldás: annyi paraméter, ahány elem (@v0, @v1, @v2). A paraméterek nevét a program számolja ki (sorszámokból), nem a felhasználó szövegéből, ezért az SQL szerkezete biztonságos marad:
public static DataTable DolgozokVarosokban(string[] varosok)
{
DataTable tabla = new DataTable();
if (varosok.Length == 0)
{
return tabla; // az IN () üres lista hibás SQL lenne
}
// @v0, @v1, @v2 ... a program által képzett nevek
string[] nevek = new string[varosok.Length];
for (int i = 0; i < varosok.Length; i++)
{
nevek[i] = "@v" + i;
}
string sql = "SELECT id, vnev, knev, fizetes, cim FROM adatok WHERE cim IN (" + string.Join(", ", nevek) + ") ORDER BY cim, vnev";
using (SQLiteConnection kapcsolat = UjKapcsolat())
{
kapcsolat.Open();
using (SQLiteCommand parancs = new SQLiteCommand(sql, kapcsolat))
{
for (int i = 0; i < varosok.Length; i++)
{
parancs.Parameters.AddWithValue(nevek[i], varosok[i]);
}
using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(parancs))
{
adapter.Fill(tabla);
}
}
}
return tabla;
}Length.@v0, @v1, @v2.@v0, @v1 alakú nevek, amelyeket egy ciklus ad. Az értékek (a városok nevei) paraméterként utaznak.IN () érvénytelen SQL, ezért előbb kilépünk, ha nincs kijelölt elem.Biztonságos hibakezelés
Eddig a hibát az ex.Message szövegével mutattuk meg. Tanuláskor ez hasznos, mert látod, mi romlott el. Egy kész programban viszont az adatbázis hibaüzenete belső részleteket árulhat el (táblák, oszlopok és fájlok nevét, az SQL szövegét), amelyek egy támadónak vagy egy kíváncsi felhasználónak támpontot adnak. A jó gyakorlat: a felhasználó általános, érthető üzenetet kap, a részletek pedig a naplóba kerülnek, ahol a fejlesztő megnézheti.
public static void Naploz(Exception ex)
{
try
{
string utvonal = System.IO.Path.Combine(Application.StartupPath, "hibanaplo.txt");
string sor = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " | " + ex.GetType().Name + " | " + ex.Message + Environment.NewLine;
System.IO.File.AppendAllText(utvonal, sor);
}
catch (Exception)
{
// a naplózás hibája ne okozzon újabb hibát
}
}
// a gombban:
catch (Exception ex)
{
DB.Naploz(ex);
MessageBox.Show("Az adatok betöltése most nem sikerült. Próbáld újra később!");
}SQLiteException), segíti a hibakeresést.ex.Message látszik a MessageBox-ban, mert hibakereséshez kell. Éles programban használd ezt a naplózós változatot.Biztonsági ellenőrzőlista az SQL-hez
(1) A felhasználó szövege csak paraméterként kerül az SQL-be. (2) Az SQL-be fűzött rész (oszlopnév, irány, paraméternevek) a program rögzített szövegeiből vagy sorszámokból áll. (3) A bevitelt a paraméter átadása előtt a megfelelő típusra alakítod és ellenőrzöd. (4) A LIKE speciális karaktereit védi az ESCAPE. (5) A hibaüzenet nem árul el belső részleteket. (6) A jelszó nem kerül naplóba vagy listába.
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. A paraméter idézőjelek között
WHERE nev = '@nev'Hiba és javítás
Az aposztrófok közé tett @nev már szó szerinti szöveg, nem paraméter: az adatbázis a @nev szöveget keresi, nem a paraméter értékét. A paraméter után nem kell idézőjel: WHERE nev = @nev. Ez az egyik leggyakoribb kezdő hiba: nincs hibaüzenet, csak üres az eredmény.
2. A LIKE minta összefűzve
string sql = "SELECT * FROM esemenyek WHERE nev LIKE '%" + txtNev.Text + "%'";Hiba és javítás
A beírt szöveg az SQL része lett: biztonsági kockázat, és az aposztróf hibát okoz. Javítás: WHERE nev LIKE @minta, és a % jeleket a C# kód fűzi a paraméter értékéhez: "%" + LikeVedelem(nev) + "%".
3. A dátumok rossz sorrendben
Az események dátuma A szöveges összehasonlítás a karakterek sorrendjét nézi, ezért a nap–hónap–év formátum nem időrendben rendez. Tárold a dátumot ISO formátumban (06.06.2026 alakban van tárolva, és a BETWEEN furcsa eredményt ad.Ok és javítás
yyyy-MM-dd), és az átadásnál is ugyanezt használd az InvariantCulture megadásával.
4. A százalékjel mindent megtalál
Egy felhasználó A 100% kifejezésre keres, de az összes esemény megjelenik.Ok és javítás
% a LIKE mintában speciális karakter. A javítás: a minta speciális karaktereit védeni kell (LikeVedelem), és az SQL-ben az ESCAPE '^' kulcsszót is meg kell adni. Csak az egyik nem elég.
5. Az IN lista üresen hiba
WHERE cim IN ()
// SQLiteException: near ")": syntax errorHiba és javítás
Ha egyetlen város sincs kijelölve, az IN zárójele üres, és az SQL érvénytelen. A metódus elején ellenőrizd a lista hosszát: ha nulla, térj vissza üres eredménnyel, vagy jelezd a felhasználónak, hogy válasszon.
6. Szöveg a számmező helyett
parancs.Parameters.AddWithValue("@maxar", txtAr.Text); // txtAr.Text: "2 500"Hiba és javítás
A szóközt tartalmazó szöveg nem szám, a lekérdezés ezért nem a várt módon összehasonlít. Alakítsd előbb számmá (int.TryParse), jelezz hibás bevitelnél, és számként add át. Ügyelj arra is, hogy a TryParse a gép nyelvi beállítása szerint értelmez (például az ezres tagoló szóközt vagy a tizedesvesszőt).
Mini projekt: eseménykereső
Készíts keresőt az esemenyek táblához:
- Az ablakon:
txtNev(névrészlet),dtpTolésdtpIg(dátumsáv),nudMaxAr(legnagyobb ár, alapérték 100000), egydgvEsemenyektáblázat és egylblDarabfelirat. - A
DB.Esemenyekmetódus a leckében látott módon:LIKE ... ESCAPE,BETWEENISO dátumokkal, az ár szűrője. - Ha a kezdő dátum a vég utáni, a program jelezzen, és ne kérdezzen.
- Minden szűrő változása frissítse a listát (a
betoltvevédelemmel, mint a 3.5 leckében). - Teszteld:
100%,_, ékezetes betűk, egy napos sáv, nulla találat.
Megoldás megnyitása (próbáld ki előbb önállóan!)
A DB.Esemenyek a leckében szerepel. Az ablak kódja a 3.5 lecke keresőjét követi:
private bool betoltve = false;
private void Form1_Load(object sender, EventArgs e)
{
dtpTol.Value = new DateTime(2026, 1, 1);
dtpIg.Value = new DateTime(2027, 12, 31);
nudMaxAr.Value = 100000;
betoltve = true;
Frissit();
}
private void Frissit()
{
if (!betoltve)
{
return;
}
if (dtpTol.Value.Date > dtpIg.Value.Date)
{
lblDarab.Text = "A kezdő dátum nem lehet a vég után!";
return;
}
try
{
DataTable tabla = DB.Esemenyek(txtNev.Text.Trim(), dtpTol.Value, dtpIg.Value, (int)nudMaxAr.Value);
dgvEsemenyek.DataSource = tabla;
lblDarab.Text = tabla.Rows.Count == 0 ? "Nincs találat." : tabla.Rows.Count + " találat";
}
catch (Exception ex)
{
DB.Naploz(ex);
MessageBox.Show("Az adatok betöltése most nem sikerült.");
}
}
private void Szuro_Valtozott(object sender, EventArgs e)
{
Frissit();
}Mit tegyél ide: a kész eseménykereső egy 100% kereséssel, amelyben csak a „Bál: 100% jókedv” esemény látszik.Javasolt fájlnév: winforms-3-7-kesz.webp · Alt szöveg: Az eseménykereső a százalékjelre védetten keres
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Több város egyszerre
Egy A bejelölt elemeket (clbVarosok CheckedListBox mutassa a városokat (SELECT DISTINCT cim). A btnSzur gomb csak a bejelölt városok dolgozóit mutassa a táblázatban. Ha nincs bejelölt város, szóljon.Egy lehetséges megoldás
CheckedItems) egy tömbbe gyűjtjük, amelyet a DB.DolgozokVarosokban metódus kap meg (lásd az 5. szakaszt).private void btnSzur_Click(object sender, EventArgs e)
{
if (clbVarosok.CheckedItems.Count == 0)
{
lblDarab.Text = "Jelölj be legalább egy várost!";
return;
}
string[] valasztott = new string[clbVarosok.CheckedItems.Count];
for (int i = 0; i < valasztott.Length; i++)
{
valasztott[i] = clbVarosok.CheckedItems[i].ToString();
}
dgvDolgozok.DataSource = DB.DolgozokVarosokban(valasztott);
}
2. Események betöltése szövegből
Egy többsoros Egyetlen parancsobjektumot használunk, és ciklusonként csak a paraméterek értékét cseréljük. Minden sort ellenőrzünk (három rész, az ár szám, a dátum érvényes), és a dátumot ISO formátumra alakítjuk. Sok sornál (több száz) egy tranzakcióban érdemes futtatni, ezt a 3.10 leckében tanuljuk.txtLista mezőbe soronként így gépelnek eseményeket: Szalagavató;3500;2026-11-20. A btnBetolt gomb vegye fel őket az adatbázisba. A hibás sorokat hagyja ki, és a végén írja ki, hány sor került be és hány hibás volt.Egy lehetséges megoldás
private void btnBetolt_Click(object sender, EventArgs e)
{
int jo = 0;
int hibas = 0;
using (SQLiteConnection kapcsolat = DB.UjKapcsolat())
{
kapcsolat.Open();
using (SQLiteCommand parancs = new SQLiteCommand("INSERT INTO esemenyek (nev, datum, ar) VALUES (@nev, @datum, @ar)", kapcsolat))
{
parancs.Parameters.Add("@nev", System.Data.DbType.String);
parancs.Parameters.Add("@datum", System.Data.DbType.String);
parancs.Parameters.Add("@ar", System.Data.DbType.Int32);
foreach (string sor in txtLista.Lines)
{
if (sor.Trim().Length == 0)
{
continue;
}
string[] reszek = sor.Split(';');
int ar;
DateTime datum;
if (reszek.Length != 3 || reszek[0].Trim().Length == 0 || !int.TryParse(reszek[1], out ar) || !DateTime.TryParse(reszek[2], out datum))
{
hibas = hibas + 1;
continue;
}
parancs.Parameters["@nev"].Value = reszek[0].Trim();
parancs.Parameters["@datum"].Value = datum.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
parancs.Parameters["@ar"].Value = ar;
parancs.ExecuteNonQuery();
jo = jo + 1;
}
}
}
lblEredmeny.Text = $"{jo} sor bekerült, {hibas} hibás volt.";
}
3. Általános hibaüzenet és napló
Írd át a dolgozói kereső (3.5) hibakezelését: a felhasználó általános üzenetet kapjon, a részletek pedig kerüljenek a Hibát például úgy idézhetsz elő, hogy ideiglenesen elírod a tábla nevét az SQL-ben. A program mutasson általános üzenetet, a hibanaplo.txt fájlba. Hogyan ellenőrzöd, hogy működik?Egy lehetséges megoldás
hibanaplo.txt (a bin mappában) pedig tartalmazza a részleteket. A teszt végén javítsd vissza a nevet.catch (Exception ex)
{
DB.Naploz(ex);
MessageBox.Show("A lista betöltése most nem sikerült.");
}
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Az eseménykereső projektje és az esemenyek tábla kell hozzá. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Melyik biztonságos?
Döntsd el, hogy melyik kódrészlet biztonságos, és melyik nem: (a) biztonságos: paraméterezett érték. (b) nem biztonságos: a felhasználó szövege az SQL része. (c) biztonságos: a program rögzített szövegeiből áll. (d) nem biztonságos: a legördülő lista szövege (a
(a) "... WHERE nev = @nev" és AddWithValue("@nev", txtNev.Text)
(b) "... WHERE nev = '" + txtNev.Text + "'"
(c) "... ORDER BY " + sorrend, ahol a sorrend egy if–else láncból kapja a szöveget
(d) "... ORDER BY " + cmbOszlop.TextMegoldás megnyitása
Text) módosítható, ha szerkeszthető a lista, és más helyről is jöhet. Rögzített lista esetén is jobb a sorszámra (SelectedIndex) építeni, és a szövegeket a kódban tartani.
2. Javítsd a lekérdezést
Javítsd ki: A paraméter az aposztrófok között szó szerinti szöveg lett, ráadásul a SELECT * FROM esemenyek WHERE nev LIKE '%@minta%'.Megoldás megnyitása
% jelek is az SQL-ben vannak. A helyes forma: WHERE nev LIKE @minta, és a C# kód állítja össze a mintát: "%" + szoveg + "%".string sql = "SELECT * FROM esemenyek WHERE nev LIKE @minta";
parancs.Parameters.AddWithValue("@minta", "%" + txtNev.Text + "%");
Közepes szint
3. Ár ellenőrzése átadás előtt
A A txtMaxAr mezőbe írt szöveget alakítsd számmá, ellenőrizd (nemnegatív egész), és csak utána add át a lekérdezésnek. Hibás bevitelnél az ErrorProvider jelezzen.Megoldás megnyitása
TryParse sikerét és az érték tartományát is vizsgáljuk. Hibánál a hibajel a mező mellett jelenik meg (1.11 lecke), és a lekérdezés nem fut le.int maxAr;
if (!int.TryParse(txtMaxAr.Text, out maxAr) || maxAr < 0)
{
epHiba.SetError(txtMaxAr, "Nemnegatív egész számot adj meg!");
return;
}
epHiba.SetError(txtMaxAr, "");
dgvEsemenyek.DataSource = DB.Esemenyek(txtNev.Text.Trim(), dtpTol.Value, dtpIg.Value, maxAr);
4. Időponttal tárolt dátum
A tábla dátuma mostantól időt is tartalmaz (2026-06-06 18:30). Írd át a szűrést úgy, hogy a kiválasztott záró nap eseményei is megjelenjenek. A záró határt a következő nap kezdetére állítjuk, és Megoldás megnyitása
< jellel hasonlítunk. A DateTime.AddDays(1) a következő napot adja.string sql = "SELECT id, nev, datum, ar FROM esemenyek WHERE datum >= @tol AND datum < @kovetkezo ORDER BY datum";
parancs.Parameters.AddWithValue("@tol", IsoDatum(tol));
parancs.Parameters.AddWithValue("@kovetkezo", IsoDatum(ig.AddDays(1)));
Kihívás szint
5. Pontos szó szerinti keresés
Hogyan működne az alsó vonásra ( Védelem nélkül mindkét jel helyettesítő karakter marad: a _) és a százalékjelre (%) való keresés a LikeVedelem nélkül, és mi a javítás? Írj tesztszöveget is.Megoldás megnyitása
_ egy tetszőleges karaktert, a % bármennyi karaktert jelent, ezért a keresés túl sok találatot ad. A javítás a LikeVedelem metódus és az ESCAPE '^' együtt. Teszteld: 100% → egy találat; _ → egy találat (Farsang_2027); ^ → nulla találat (és nem hiba); a% → csak a szó szerint a% tartalmazó nevek (nulla).
6. Kódátnézés
Keress legalább öt hibát (biztonsági vagy pontossági) az alábbi kódban, és javítsd őket:
string sql = "SELECT * FROM esemenyek WHERE nev LIKE '%" + txtNev.Text + "%' AND datum >= '"
+ dtpTol.Text + "' AND ar <= " + txtAr.Text + " ORDER BY " + cmbRend.Text;
try
{
// ... végrehajtás ...
}
catch (Exception ex)
{
MessageBox.Show(sql + Environment.NewLine + ex.Message);
}Megoldás megnyitása
(1) A nev beírt szövege összefűzve: SQL-befecskendezés, paraméter kell. (2) A LIKE speciális karaktereit nem védi az ESCAPE. (3) A dtpTol.Text a gép nyelvi formátumában (nem ISO) kerül be, ezért a dátumok összehasonlítása rossz. (4) Az txtAr.Text szám helyett szövegként van összefűzve: nincs TryParse, és ez is befecskendezési felület. (5) Az ORDER BY a cmbRend.Text szövegét fűzi: rögzített szövegekből kell választani a SelectedIndex alapján. (6) A hibaüzenet kiírja az SQL szövegét és a belső hibát a felhasználónak: általános üzenet és napló kell.
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Mert az érték külön utazik, ezért az aposztróf, a tizedesvessző és a speciális karakterek nem borítják fel az SQL szerkezetét. Hogy a hibás bevitel az adatbázis előtt kiderüljön, és a paraméter szám típusú legyen, ne szöveg. ISO szöveges formátumban ( A Annyi paramétert használsz, ahány elem van ( Általános, érthető üzenetet. A részletek a naplóba kerülnek. Az aposztrófok között a 1. Miért pontosabb a paraméter az összefűzésnél?
2. Miért kell a bevitelt előbb számmá alakítani?
3. Hogyan tárold a dátumot az SQLite-ban?
yyyy-MM-dd), mert így a szöveges sorrend megegyezik az időrenddel.4. Mit védi az ESCAPE?
LIKE minta speciális karaktereit (%, _): a védőkarakter után álló jel szó szerint értendő.5. Hogyan szűrsz változó hosszúságú listára?
@v0, @v1, ...). A paraméterek neveit a program képzi sorszámokból.6. Mit kapjon a felhasználó hiba esetén?
7. Mi a baj a
WHERE nev = '@nev' alakkal?@nev szó szerinti szöveg, nem paraméter.
Mit tudsz már?
- A bevitelt a paraméter előtt típusra alakítod és ellenőrzöd.
- A dátumot ISO formátumban tárolod és szűröd.
- A
LIKEspeciális karaktereit azESCAPEvédi. - Változó hosszúságú
INlistát építesz biztonságosan. - A hibákat általános üzenettel és naplóval kezeled.
Következő lecke: DataAdapter, DataTable és DataSource
A lekérdezéseket már biztonságosan írod. A következő leckében a letöltött adatokkal dolgozunk a program oldalán: szűrés, rendezés és keresés a DataTable-ben.




