Grafikus C# – Windows Forms tanfolyam › 3.8 lecke Windows Forms · 3.8 lecke · adatok a memóriában Eddig minden szűrőváltozásnál újra lekérdeztük az adatbázist. Kisebb adatmennyiségnél van egy gyorsabb és sokszor kényelmesebb út is: egyszer betöltöd az adatokat egy DataAdapter, DataTable és DataSource – adatok a memóriában
DataTable-be, és ott szűrsz, rendezel, számolsz. Ebben a leckében a DataTable sorait és oszlopait, a DataView szűrését és rendezését, a kifejezés-oszlopokat és az összesítő Compute metódust ismered meg. Közben az ékezetes keresés problémájára is megoldást kapsz.
A lecke végére
- érted, mit tárol a
DataTable(oszlopok, sorok, értékek), és hogyan olvasod ki a sorait; - kezeled a hiányzó (
DBNull) értékeket azIsNullés aDBNull.Valuesegítségével; - a
DataView.RowFilterés aSorttulajdonsággal szűrsz és rendezel az adatbázis újabb lekérdezése nélkül; - a szűrő szövegét helyesen védi (aposztróf, speciális karakterek);
- kifejezés-oszlopot adsz a táblához (
fizetes * 12,IIF), és összesítést kérsz aComputemetódussal; - döntesz arról, mikor érdemes a memóriában, és mikor az adatbázisban szűrni.
Mielőtt elkezded
Ehhez a leckéhez kell a 3.4 lecke (DataTable, DataGridView), a 3.5 lecke (a dolgozói adatok, LIKE) és a 3.7 lecke (a paraméterek és az ékezetes keresés problémája).
A DataTable: oszlopok, sorok, értékek
A DataTable egy memóriában lévő táblázat. Az SQLiteDataAdapter.Fill az adatbázisból tölti fel: létrehozza az oszlopokat (az SQL oszlopneveivel), és a sorokat az értékekkel. A DataTable három fontos része:
tabla.Columns["vnev"]. Az oszlop DataType tulajdonsága az értékek típusa.DataRow objektumok). A Rows.Count a sorok száma.object típusban. Szöveggé a ToString(), számmá a Convert alakítja.sor.IsNull("oszlop") igaz, ha nincs érték.DataTable tabla = DB.Osszes(); // a 3.6 leckéből: id, vnev, knev, fizetes, cim
long osszeg = 0;
int nincsFizetes = 0;
foreach (DataRow sor in tabla.Rows)
{
string nev = sor["vnev"].ToString() + " " + sor["knev"].ToString();
if (sor.IsNull("fizetes"))
{
nincsFizetes = nincsFizetes + 1;
}
else
{
osszeg = osszeg + Convert.ToInt64(sor["fizetes"]);
}
}
lblEredmeny.Text = $"{tabla.Rows.Count} dolgozó, a fizetések összege: {osszeg} Ft, fizetés nélkül: {nincsFizetes}";Az SQLite egész számai Int64 típusúak
Az SQLite INTEGER oszlopa a DataTable-ben Int64 (long) típusú lesz, nem int. Ezért ajánlott a Convert.ToInt32 vagy a Convert.ToInt64 használata a közvetlen (int) típusátalakítás helyett: az (int)sor["fizetes"] egy object-ből kicsomagolás, amely hibát (InvalidCastException) dob, ha a belső típus long.
Jósolj!
A tabla.Rows.Count értéke 9, és az egyik dolgozó fizetése NULL. Mi történik a fenti ciklusban a Convert.ToInt64(sor["fizetes"]) hívással, ha nincs az IsNull ellenőrzés?
Jóslat ellenőrzése
A Convert.ToInt64(DBNull.Value) InvalidCastException kivételt dob, mert a DBNull nem alakítható számmá. A hiba éppen a NULL fizetésű sornál jelentkezne, ezért a program látszólag jól működik, amíg olyan adat nem kerül a táblába. Az IsNull ellenőrzés a megoldás.
DataView: szűrés és rendezés újabb lekérdezés nélkül
A DataView a DataTable egy nézete: ugyanazokat a sorokat mutatja, de szűrve és rendezve. Az eredeti tábla nem változik. A táblázat (DataGridView) adatforrása lehet a nézet is:
private DataTable tabla;
private DataView nezet;
private void Form1_Load(object sender, EventArgs e)
{
tabla = DB.Osszes(); // egyetlen lekérdezés az adatbázisból
nezet = new DataView(tabla);
dgvDolgozok.DataSource = nezet; // a táblázat a nézetet mutatja
}
// példák a szűrőre és a rendezésre:
nezet.RowFilter = "cim = 'Győr'";
nezet.RowFilter = "fizetes >= 400000 AND cim = 'Pécs'";
nezet.RowFilter = "vnev LIKE 'K%'";
nezet.RowFilter = ""; // nincs szűrő: minden sor látszik
nezet.Sort = "fizetes DESC";
nezet.Sort = "cim, fizetes DESC";
lblDarab.Text = nezet.Count + " találat";WHERE részéhez (=, <>, >, AND, OR, LIKE, IN). A szöveges értéket aposztróf közé kell tenni. Ez nem SQL parancs: az adatbázishoz nem fordul, a memóriában szűr.DESC a csökkenőhöz. Az üres szöveg az eredeti sorrendet adja.tabla.Rows.Count mindig az összes sort mutatja.Jósolj!
A nézetre RowFilter = "cim = 'Győr'" szűrőt állítasz. Hány sora van ezután a tabla.Rows gyűjteménynek, és hány a nezet-nek? Törlődtek-e a többi város sorai?
Jóslat ellenőrzése
A tabla.Rows továbbra is az összes sort tartalmazza (például 9-et), a nezet csak a győrieket (például 3-at). A szűrő nem töröl semmit: a többi sor a táblában marad, csak a nézetben nem látszik. A szűrő kikapcsolása (RowFilter = "") azonnal visszahozza őket, adatbázis-hívás nélkül.
A kis- és nagybetű, és az ékezetek
A DataTable alapból a kis- és nagybetű különbségét figyelmen kívül hagyja a szűrésnél (CaseSensitive: False), és ezt az aktuális nyelvi beállítás szerint teszi. Ezért a vnev LIKE 'á%' a memóriában megtalálja az Árpád nevet is, szemben az SQLite LIKE operátorával (3.7 lecke). Az ékezet nélküli keresést (arpad → Árpád) viszont ez sem oldja meg: ehhez a gyakorlótárban látsz megoldást.
A szűrőszöveg védelme
A RowFilter nem SQL, nincs mögötte adatbázis, ezért nincs értelme SQL-befecskendezésről beszélni. Ennek ellenére a felhasználó szövegét itt sem szabad nyersen beírni a szűrő szövegébe: egy aposztróf (O'Hara) vagy egy csillag a szűrőt szintaktikailag hibássá teszi (SyntaxErrorException), vagy másképp működik, mint várnád. A RowFilter-hez nincs paraméter, ezért a védelmet a szöveg előkészítése adja:
// a RowFilter LIKE mintájában a [ ] * % jeleket szögletes zárójelbe kell tenni,
// az aposztrófot pedig meg kell kettőzni
private static string FilterVedelem(string szoveg)
{
string eredmeny = "";
foreach (char c in szoveg)
{
if (c == '[' || c == ']' || c == '*' || c == '%')
{
eredmeny = eredmeny + "[" + c + "]";
}
else if (c.ToString() == "'")
{
eredmeny = eredmeny + "''";
}
else
{
eredmeny = eredmeny + c;
}
}
return eredmeny;
}
private void SzuroFrissit()
{
string szoveg = txtSzuro.Text.Trim();
if (szoveg.Length == 0)
{
nezet.RowFilter = "";
}
else
{
string v = FilterVedelem(szoveg);
nezet.RowFilter = "vnev LIKE '%" + v + "%' OR knev LIKE '%" + v + "%'";
}
lblDarab.Text = nezet.Count + " találat";
}RowFilter LIKE mintájában a * és a % helyettesítő karakter. Szó szerinti használatukhoz szögletes zárójelbe kell tenni őket ([*]).O''Hara).Replace), a második csere az elsőnek a saját zárójeleit is átírná. A ciklus minden karaktert egyszer dolgoz fel.Jósolj!
A felhasználó a O'Hara szöveget írja a szűrőmezőbe, de a program FilterVedelem nélkül, egyszerű összefűzéssel építi a RowFilter szövegét. Mi történik?
Jóslat ellenőrzése
A szűrő szövege vnev LIKE '%O'Hara%' lesz: az aposztróf lezárja a szöveges értéket, a maradék szintaktikailag hibás, ezért a RowFilter értékadásakor SyntaxErrorException keletkezik, és a program gépelés közben összeomlik, ha nincs kezelve. A FilterVedelem a szöveget O''Hara alakra cseréli, és a szűrő hibátlan.
Kifejezés-oszlop és Compute
A DataTable számított oszlopokat is tud: az oszlop értékét egy kifejezés adja meg a többi oszlopból, és a program magától frissíti. Az Compute metódus pedig a sorokból összesítést számol (összeg, átlag, darabszám, legnagyobb), a RowFilter-hez hasonló szűrő mellett:
tabla = DB.Osszes();
// számított oszlopok
tabla.Columns.Add("evesFizetes", typeof(long), "fizetes * 12");
tabla.Columns.Add("besorolas", typeof(string), "IIF(fizetes >= 400000, 'magas', 'átlagos')");
nezet = new DataView(tabla);
dgvDolgozok.DataSource = nezet;
// összesítés a nézet aktuális szűrőjével
object osszeg = tabla.Compute("SUM(fizetes)", nezet.RowFilter);
object atlag = tabla.Compute("AVG(fizetes)", nezet.RowFilter);
if (osszeg == DBNull.Value)
{
lblOsszesites.Text = "Nincs adat.";
}
else
{
lblOsszesites.Text = $"Összeg: {Convert.ToInt64(osszeg):N0} Ft, átlag: {Convert.ToDouble(atlag):N0} Ft";
}typeof(long) az érték típusa, a harmadik paraméter a kifejezés.?: operátora). A szövegeket itt is aposztróf közé kell tenni.SUM, AVG, COUNT, MIN, MAX használható. Ha nincs egyetlen sor sem, az eredmény DBNull.Value.A számított oszlop NULL-ra NULL
Ha egy dolgozó fizetése NULL, akkor a fizetes * 12 kifejezés is NULL lesz. Az IIF(fizetes >= 400000, ...) ilyenkor a hamis ágat választja (az összehasonlítás nem igaz), ezért a hiányzó fizetésű dolgozó átlagos besorolású lenne. Ha ez nem kívánatos, a kifejezésbe külön ágat kell írni (IIF(fizetes IS NULL, 'nincs adat', ...)).
Mit tegyél ide: a futó elemző: a táblázatban az éves fizetés és a besorolás oszlop is látszik, alatta az összeg és az átlag felirata.Javasolt fájlnév: winforms-3-8-elemzo.webp · Alt szöveg: A dolgozó-elemző számított oszlopokkal és összesítéssel
Memóriában vagy az adatbázisban szűrjünk?
| Szempont | Szűrés a memóriában (DataView) | Szűrés az adatbázisban (WHERE) |
|---|---|---|
| Sebesség gépeléskor | Azonnali, nincs adatbázis-hívás. | Minden változás új lekérdezés. |
| Adatmennyiség | Kis és közepes (néhány ezer sor). | Nagy adatmennyiségnél is jó. |
| Friss adat | Csak a betöltés pillanatának állapotát látja. | Mindig az aktuális állapotot adja. |
| Kis- és nagybetű, ékezet | A nyelvi beállítás szerint kezeli a kis- és nagybetűt. | Az SQLite LIKE csak az ASCII betűknél. |
| Biztonság | Nincs SQL, de a szűrőszöveget védeni kell. | Paraméterek (3.3, 3.7 lecke). |
Ökölszabály
Egy kisebb nyilvántartásnál (néhány ezer sor) töltsd be egyszer az adatokat, és szűrj a memóriában: gyors és kényelmes. Ha az adatok nagyok vagy sokan módosítják őket, a szűrést bízd az adatbázisra. A betöltés után mindig érdemes egy Frissítés gombot adni, amely újra lekérdezi az adatokat.
A táblázatban szerkesztett érték nem kerül az adatbázisba
Ha a DataGridView szerkeszthető, és a felhasználó átír egy cellát, az csak a memóriában lévő DataTable-t módosítja. Az adatbázis változatlan marad, és az adat a program újraindításakor elveszik. Az adatbázis módosításához UPDATE utasítás kell (3.6 lecke), vagy az adapter visszaíró funkciója, amelyet a 3.9 leckében nézünk meg.
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 szűrés nem látszik a táblázatban
dgvDolgozok.DataSource = tabla;
nezet.RowFilter = "cim = 'Győr'";Hiba és javítás
A táblázat a tabla objektumot mutatja, a szűrő viszont a nezet nézeten van, így a táblázatban nem látszik semmi változás. A DataSource a nézet legyen: dgvDolgozok.DataSource = nezet;
2. Hibás oszlopnév a szűrőben
nezet.RowFilter = "fizetés > 400000";
// EvaluateException: Cannot find column [fizetés].Hiba és javítás
Az oszlop neve fizetes (ékezet nélkül), a szűrőben viszont ékezettel szerepel. A RowFilter és a Sort az oszlop pontos nevét várja. Ellenőrizd a tabla.Columns neveit, vagy írd ki őket ciklussal.
3. Szám összehasonlítása szöveggel
nezet.RowFilter = "fizetes > '400000'";
// EvaluateException: Cannot perform '>' operation on System.Int64 and System.String.Hiba és javítás
A számot nem szabad aposztróf közé tenni: az aposztróf szöveget jelent. A helyes alak: fizetes > 400000. A szöveges oszlopok értékét viszont aposztróf közé kell írni.
4. InvalidCastException a NULL értéknél
long fizetes = (long)sor["fizetes"];Hiba és javítás
Ha az érték DBNull.Value, a kicsomagolás hibát dob. Előbb ellenőrizd: sor.IsNull("fizetes"), és használd a Convert.ToInt64 metódust.
5. Az átírt cella nincs az adatbázisban
A táblázatban átírod egy dolgozó nevét, de a program újraindítása után a régi név látszik. A Ok és javítás
DataGridView csak a memóriában lévő DataTable-t módosította. Az adatbázishoz mentés kell: UPDATE utasítás (3.6 lecke) vagy az adapter visszaírása (3.9 lecke). Ha csak megtekintésre szánod a táblázatot, állítsd a ReadOnly tulajdonságot True értékre.
6. SyntaxErrorException gépelés közben
A szűrőmezőbe aposztrófot gépelve a program leáll. A felhasználó szövege nyersen került a Ok és javítás
RowFilter szövegébe. A szöveg előkészítése (FilterVedelem) kettőzi az aposztrófot és védi a speciális karaktereket. A RowFilter értékadását érdemes try–catch blokkal is védeni, és hiba esetén a szűrőt üresre állítani.
Mini projekt: dolgozó-elemző
Készíts elemző ablakot a dolgozók adataihoz:
- Betöltés indításkor egyetlen lekérdezéssel (
DB.Osszes()), két számított oszloppal:evesFizetesésbesorolas. - Egy
txtSzuromező élő szűrése a névre aFilterVedelemsegítségével. - Egy
cmbRendezeslista a rendezéshez (név, fizetés növekvő és csökkenő, város szerint), rögzített szövegekből választva. - Egy
lblOsszesitesfelirat a látható sorok darabszámával, összegével és átlagával; nulla találatnál Nincs adat. - Egy
btnFrissitgomb, amely újra betölti az adatokat az adatbázisból, és megtartja a szűrőt és a rendezést. - Teszteld:
O'Hara,[,*,%a keresőben, üres szűrő, NULL fizetésű sor.
Megoldás megnyitása (próbáld ki előbb önállóan!)
A szűrés és az összesítés közös metódusban (NezetFrissit()) fut, amelyet minden vezérlő eseménye hív. A btnFrissit csak a tabla adatait cseréli (új Fill), a nézet a szűrőt és a rendezést megtartja, ha ugyanazt a DataView objektumot használod.
private DataTable tabla;
private DataView nezet;
private bool betoltve = false;
private void Betoltes()
{
tabla = DB.Osszes();
tabla.Columns.Add("evesFizetes", typeof(long), "fizetes * 12");
tabla.Columns.Add("besorolas", typeof(string), "IIF(fizetes >= 400000, 'magas', 'átlagos')");
nezet = new DataView(tabla);
dgvDolgozok.DataSource = nezet;
}
private void Form1_Load(object sender, EventArgs e)
{
cmbRendezes.Items.Add("Név szerint");
cmbRendezes.Items.Add("Fizetés szerint, csökkenő");
cmbRendezes.Items.Add("Fizetés szerint, növekvő");
cmbRendezes.Items.Add("Város szerint");
cmbRendezes.SelectedIndex = 0;
try
{
Betoltes();
}
catch (Exception ex)
{
DB.Naploz(ex);
MessageBox.Show("Az adatok betöltése nem sikerült.");
return;
}
betoltve = true;
NezetFrissit();
}
private void NezetFrissit()
{
if (!betoltve)
{
return;
}
string szoveg = txtSzuro.Text.Trim();
if (szoveg.Length == 0)
{
nezet.RowFilter = "";
}
else
{
string v = FilterVedelem(szoveg);
nezet.RowFilter = "vnev LIKE '%" + v + "%' OR knev LIKE '%" + v + "%'";
}
string sorrend = "vnev, knev";
if (cmbRendezes.SelectedIndex == 1)
{
sorrend = "fizetes DESC";
}
else if (cmbRendezes.SelectedIndex == 2)
{
sorrend = "fizetes ASC";
}
else if (cmbRendezes.SelectedIndex == 3)
{
sorrend = "cim, vnev";
}
nezet.Sort = sorrend;
object osszeg = tabla.Compute("SUM(fizetes)", nezet.RowFilter);
object atlag = tabla.Compute("AVG(fizetes)", nezet.RowFilter);
if (nezet.Count == 0 || osszeg == DBNull.Value)
{
lblOsszesites.Text = "Nincs adat.";
}
else
{
lblOsszesites.Text = $"{nezet.Count} dolgozó | összeg: {Convert.ToInt64(osszeg):N0} Ft | átlag: {Convert.ToDouble(atlag):N0} Ft";
}
}
private void SzuroValtozott(object sender, EventArgs e)
{
NezetFrissit();
}
private void btnFrissit_Click(object sender, EventArgs e)
{
try
{
DataTable uj = DB.Osszes();
tabla.Clear();
foreach (DataRow sor in uj.Rows)
{
tabla.ImportRow(sor);
}
NezetFrissit();
}
catch (Exception ex)
{
DB.Naploz(ex);
MessageBox.Show("A frissítés nem sikerült.");
}
}Mit tegyél ide: a kész elemző a szűrővel és az összesítéssel: „4 dolgozó | összeg: 1 660 000 Ft | átlag: 415 000 Ft”.Javasolt fájlnév: winforms-3-8-kesz.webp · Alt szöveg: A kész dolgozó-elemző szűréssel és összesítéssel
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. A legjobban fizetettek listája
Egy gomb írja az A lstTop ListBoxba azok nevét, akiknek a fizetése 400 000 Ft felett van, fizetés szerint csökkenően (Varga Dávid: 450 000 Ft).Egy lehetséges megoldás
DataTable.Select(szűrő, rendezés) egy DataRow tömböt ad vissza, amelyen a foreach végigmegy. A Select a DataView-hoz hasonló szűrő- és rendezési szintaxist használ, de nem változtatja meg a nézetet.private void btnTop_Click(object sender, EventArgs e)
{
lstTop.Items.Clear();
DataRow[] sorok = tabla.Select("fizetes > 400000", "fizetes DESC");
foreach (DataRow sor in sorok)
{
lstTop.Items.Add(sor["vnev"] + " " + sor["knev"] + ": " + Convert.ToInt64(sor["fizetes"]).ToString("N0") + " Ft");
}
}
2. Városonkénti átlag
A A város nevét a cmbVaros kiválasztásakor a lblVarosAtlag mutassa a város átlagfizetését. A város neve aposztrófot is tartalmazhat.Egy lehetséges megoldás
Compute szűrőjébe kerüléskor védeni kell (aposztróf megkettőzése). Ha a városnak nincs adata, az eredmény DBNull.Value.private void cmbVaros_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbVaros.SelectedItem == null)
{
return;
}
string varos = cmbVaros.SelectedItem.ToString().Replace("'", "''");
object atlag = tabla.Compute("AVG(fizetes)", "cim = '" + varos + "'");
if (atlag == DBNull.Value)
{
lblVarosAtlag.Text = "Nincs adat.";
}
else
{
lblVarosAtlag.Text = "Átlagfizetés: " + Convert.ToDouble(atlag).ToString("N0") + " Ft";
}
}
3. Kategória oszlop színezéssel
Adj a táblához egy Az kategoria kifejezés-oszlopot három értékkel: alacsony (300 000 alatt), közepes (300 000 és 400 000 között), magas (400 000 fölött). A magas sorok hátterét színezd zöldre.Egy lehetséges megoldás
IIF egymásba ágyazható. A színezést a DataGridView.DataBindingComplete eseménye végzi, amely az adatok megjelenítése után fut le. A cellák értékét a Cells["kategoria"].Value adja.tabla.Columns.Add("kategoria", typeof(string), "IIF(fizetes < 300000, 'alacsony', IIF(fizetes <= 400000, 'közepes', 'magas'))");
private void dgvDolgozok_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow sor in dgvDolgozok.Rows)
{
if (Convert.ToString(sor.Cells["kategoria"].Value) == "magas")
{
sor.DefaultCellStyle.BackColor = Color.Honeydew;
}
}
}
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. A dolgozó-elemző projektje kell hozzá (a tabla és a nezet mező). Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Az oszlopok kiírása
Egy gomb írja ki az Az oszlopok a lstOszlopok ListBoxba a tabla oszlopainak nevét és típusát (fizetes: Int64).Megoldás megnyitása
Columns gyűjteményben vannak, a ColumnName a nevét, a DataType.Name a típus nevét adja. Figyeld meg, hogy az SQLite INTEGER oszlopa Int64.lstOszlopok.Items.Clear();
foreach (DataColumn oszlop in tabla.Columns)
{
lstOszlopok.Items.Add(oszlop.ColumnName + ": " + oszlop.DataType.Name);
}
2. Hány dolgozónak nincs városa?
Számold meg a sorok között azokat, amelyeknek a A cim oszlopa üres (NULL), és írd ki az eredményt.Megoldás megnyitása
sor.IsNull("cim") igaz a hiányzó értéknél. Ugyanez a szűrővel is megoldható: tabla.Select("cim IS NULL").Length.int db = 0;
foreach (DataRow sor in tabla.Rows)
{
if (sor.IsNull("cim"))
{
db = db + 1;
}
}
lblEredmeny.Text = $"Város nélküli dolgozók: {db}";
// ugyanez a szűrővel:
int db2 = tabla.Select("cim IS NULL").Length;
Közepes szint
3. Rendezés két szempont szerint
A nézet legyen rendezve városok szerint, azon belül fizetés szerint csökkenően, és a táblázat is így jelenjen meg. A Megoldás megnyitása
Sort több oszlopot is elfogad, vesszővel elválasztva, oszloponként külön DESC megadásával.nezet.Sort = "cim ASC, fizetes DESC";
4. A legjobban fizetett dolgozó
Írd ki a legjobban fizetett dolgozó nevét. Mit teszel, ha a tábla üres? A Megoldás megnyitása
Select eredménye tömb: az első elem a legjobban fizetett. Üres tábla esetén a tömb hossza nulla, és a [0] hibát (IndexOutOfRangeException) okozna, ezért előbb ellenőrizzük a hosszt. A NULL fizetésűeket csökkenő rendezésnél a végére teszi.DataRow[] sorok = tabla.Select("fizetes IS NOT NULL", "fizetes DESC");
if (sorok.Length == 0)
{
lblEredmeny.Text = "Nincs adat.";
}
else
{
lblEredmeny.Text = "Legjobban fizetett: " + sorok[0]["vnev"] + " " + sorok[0]["knev"];
}
Kihívás szint
5. Saját DataTable adatbázis nélkül
Készíts kódból egy bevásárlókosár-táblát ( A termek, db, ar, és egy kifejezés-oszlop: osszeg = db * ar), vegyél fel három sort, és jelenítsd meg a táblázatban. Egy lblVegosszeg mutassa az összesített végösszeget.Megoldás megnyitása
DataTable adatbázis nélkül is használható: az oszlopokat és a sorokat magad adod meg. A Rows.Add az értékeket az oszlopok sorrendjében várja. A kifejezés-oszlopnak nem adsz értéket, magától számolódik.DataTable kosar = new DataTable();
kosar.Columns.Add("termek", typeof(string));
kosar.Columns.Add("db", typeof(int));
kosar.Columns.Add("ar", typeof(int));
kosar.Columns.Add("osszeg", typeof(int), "db * ar");
kosar.Rows.Add("alma", 3, 300);
kosar.Rows.Add("kenyér", 1, 500);
kosar.Rows.Add("tej", 2, 400);
dgvKosar.DataSource = kosar;
object vegosszeg = kosar.Compute("SUM(osszeg)", "");
lblVegosszeg.Text = "Végösszeg: " + vegosszeg + " Ft";
6. Ékezet nélküli keresés
A kereső találja meg az Árpád nevet az arpad, a Kovács nevet pedig a kovacs beírásakor is. Hogyan oldod meg a Készítünk egy keresőoszlopot, amelybe a név ékezet nélküli, kisbetűs változata kerül, és a keresőszöveget is ugyanígy alakítjuk át. Az ékezetek eltávolítása a normalizálás segítségével történik: a DataTable-ben?Megoldás megnyitása
Normalize(NormalizationForm.FormD) az ékezetes betűt alapbetűre és külön ékezetjelre bontja (például á → a és egy ékezetjel), a ciklus pedig az ékezetjeleket kihagyja. A CharUnicodeInfo a System.Globalization, a NormalizationForm a System.Text névtérben van.private static string Ekezettelen(string szoveg)
{
string felbontott = szoveg.Normalize(NormalizationForm.FormD);
string eredmeny = "";
foreach (char c in felbontott)
{
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
{
eredmeny = eredmeny + c;
}
}
return eredmeny.Normalize(NormalizationForm.FormC).ToLower();
}
// a betöltés után: keresőoszlop minden sorhoz
tabla.Columns.Add("keresheto", typeof(string));
foreach (DataRow sor in tabla.Rows)
{
sor["keresheto"] = Ekezettelen(sor["vnev"] + " " + sor["knev"]);
}
// a szűrésnél:
string v = FilterVedelem(Ekezettelen(txtSzuro.Text.Trim()));
nezet.RowFilter = "keresheto LIKE '%" + v + "%'";
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A Szűrőkifejezés, amely a memóriában szűri a nézet sorait. Nem SQL, az adatbázishoz nem fordul. Az SQLite egész számai Mert az aposztróf és a speciális karakterek ( A többi oszlopból számolt értéket mutat (például Kis és közepes adatmennyiségnél a memóriában gyorsabb és kényelmesebb. Nagy adatnál vagy többfelhasználós használatnál az adatbázisban, hogy mindig friss adatot kapj. Nem. Csak a memóriában lévő 1. Mi a különbség a DataTable és a DataView között?
DataTable az adatokat tárolja, a DataView annak szűrt és rendezett nézete. A nézet nem módosítja a táblát.2. Mit jelent a RowFilter, és hol hajtódik végre?
3. Mi a baj az (int)sor["fizetes"] kifejezéssel?
Int64 típusúak, ezért a kicsomagolás InvalidCastException hibát dob. A Convert.ToInt32 vagy Convert.ToInt64 megoldja. A NULL értéknél előbb az IsNull vizsgálat kell.4. Miért kell védeni a RowFilter szövegét?
[ ] * %) szintaktikai hibát okozhatnak, vagy másként működnek, mint várod. Az aposztrófot kettőzni kell, a többit szögletes zárójelbe tenni.5. Mire való a kifejezés-oszlop?
fizetes * 12), és automatikusan frissül.6. Mikor szűrj a memóriában, és mikor az adatbázisban?
7. A táblázatban átírtam egy cellát. Bekerült az adatbázisba?
DataTable módosult. Az adatbázis módosításához UPDATE vagy az adapter visszaírása kell.
Mit tudsz már?
- Olvasod a
DataTablesorait, és kezeled a NULL értékeket. - A
DataViewsegítségével szűrsz és rendezel újabb lekérdezés nélkül. - Védeni tudod a szűrőszöveget.
- Kifejezés-oszlopot adsz, és összesítést kérsz a
Computesegítségével. - Eldöntöd, hol érdemes szűrni: a memóriában vagy az adatbázisban.
Következő lecke: űrlap és CRUD műveletek
A DataTable már a kezedben van. A következő leckében a teljes CRUD ciklust (létrehozás, olvasás, módosítás, törlés) egy rendezett űrlapban fogod össze.




