Feladat 3: Több-több kapcsolatok¶
A művekhez műfajok tartoznak. A műfajok a genres kulcsú elemben találhatók vesszővel elválasztva. A műfajokat saját táblában kell tárolni, hogy kevesebb helyet fogyasszanak a diszken és ne legyen redundáns a tárolásuk. A műfajról tároljuk az azonosítóját (szám), amit az adatbázis oszt majd ki, valamint a nevét, ami kötelező, és egyedinek kell lennie, és maximum 50 karakter hosszúságú lehet. Egy film több műfajban is lehet, egy műfajhoz több film is tartozhat. Mindkét irányban navigation property-t kell definiálni a műfaj és a mű között. Egy filmhez egy műfaj csak egyszer tartozhat!
Tippek¶
-
Az adatbázisban csak 1-többes kapcsolat létezik, több-többes kapcsolatot (many-to-many relationship) kapcsolótábla bevezetésével és 1-többes kapcsolatokkal oldjuk meg. C# szinten vagy egy-az-egyben ezt a modellt képezzük le (explicit több-többes kapcsolat), vagy csak egyszerűen a két eredeti entitásba veszünk fel kollekciókat, és csak az EF szinten jelenik meg a kapcsolótábla (implicit több-többes kapcsolat). Bár az utóbbi egyszerűbb és kényelmesebb, de korlátozottabb, nehezebben bővíthető.
-
Explicit esetben a
Title-ön kívül két entitást kell definiálni:- az egyik maga a műfaj (
Genre), amiben az azonosító és a név tulajdonságok szerepelnek, - a másik a kapcsolótábla,
TitleGenrenévre hallgató entitás lehet, amiben egy egyedi azonosító van, és két külső kulcs: egyTitleIdés egyGenreId, - a
TitleGenre-ban definiáljunk a külső kulcsokhoz egy-egy navigation property-t, aTitleésGenreentitásokban pedig egy-egyICollection<TitleGenre>típusút.
- az egyik maga a műfaj (
-
Hogy ne kapj fordítási figyelmeztetést
nullértékek kezelése miatt, a kollekció típusú navigációs property-ket mindig inicializáld üres listára, míg a nem kollekció típusú navigációs property-ket explicitnullértékre a null forgiving operátorral. Példa az utóbbira:public Genre Genre { get; set; } = null!; -
Ellenőrizd, hogy a
GenreésTitleGenrelétrejön-e táblaként a DB-ben! Ha nem többesszámú a neve, akkor valószínűleg kihagytad aDbSetdefinícióját aMovieCatalogDbContext-ből. -
Fontos, hogy egy mű egy műfajban csak egyszer szerepelhet, ezért unique indexet kell létrehozni a
TitleGenreentitásban a két külső kulcsra (együttesen)
modelBuilder.Entity<TitleGenre>()
.HasIndex(tg => new { tg.GenreId, tg.TitleId })
.IsUnique()
- Betöltéskor az alábbi megoldással kevés kóddal megoldhatjuk az új táblák feltöltését
- A
ImportFromFileAsyncfüggvény elején vegyünk fel egyDictionary<string, Genre>-t, amibe folyamatosan gyűjtjük aGenrepéldányokat és a műfaj neve a kulcs, így név alapján gyorsan tudunk keresni benne - Elég csak az új
Titlepéldány kitöltésekor az újTitleGenresproperty-t kitölteni, az EF automatikusan felveszi a kapcsolódó entitásokat, ha a navigációs property-k ki vannak töltve (ráadásul kapcsolatonként elég az egyik irányt kitölteni) nem kell különAddhívás. A genres mező szövegét feldaraboljuk a vesszők mentén, az így keletkezőstring[]darablista minden elemét leképezzük egy újTitleGenrepéldányra, amiben megint csak elég csak aGenrenavigációs property-t kitölteni. Itt kap szerepet az előző lépésben felvett szótár, mert kikeressük belőle, hogy az aktuális műfajszöveghez vettünk-e már felGenrepéldányt: ha igen, akkor ezt a példányt adjuk meg aGenreértékének; ha még nincs ilyen példány, akkor egyrészt felvesszük a szótárba új példányként, másrészt ugyanezt az új példányt adjuk meg aGenreértékének is. Ez a két művelet, azaz aGenreproperty beállítása egyetlen összetett kifejezéssel is lehetséges, így a LINQ kifejezésben könnyen felhasználható (ngaz aktuális műfaj, még szövegként):Genre = genres.TryGetValue(ng, out var g) ? g : genres[ng] =new Genre(ng)
- A
- Futtatás előtt érdemes most is törölni a Titles táblát, de a TRUNCATE nem használható olyan táblákon, amire idegen kulcs hivatkozás van (a Titles tábla már ilyen), helyette a
DELETE FROM táblanévhasználható. Minden tábla kitörlésére/eldobására használható adotnet ef database update 0parancssorból - ez kitörli minden táblánkat, majd a normáldotnet ef database updatelétrehozza őket üresen.
Beadandó¶
Az adatmodell kódjáról készült képek, a betöltött adatokat reprezentáló képek (a kapcsolótábla és az új tábla tartalmai) és az adatbázis sémáját reprezentáló képek (legyenek láthatók a táblák, azok oszlopai, indexei, kulcsai pl. SQL Server Object Explorerben vagy SSMS-ben).
Bónusz (nehéz!): egy jegy javítás kapható, ha a teljes adathalmazt tartalmazó fájl betöltése megtörténik! Ekkor beadandó még rövid magyarázat a megoldás módjáról és tetszőleges módon demonstrálandó, hogy ténylegesen bekerült adatbázisba az összes adat (kimutatható minden táblának a számossága). Ezt a pull request szövegébe írd be.
Következő feladat¶
Folytasd a következő feladattal.