Softver
20.08.2024 13:34

Podijelite s drugima:

Udio

Objektno-relacijsko preslikavanje s Entity Frameworkom

Danas je World Wide Web najpopularnija usluga najveće računalne mreže Interneta. Više od 100.000 novih web stranica pridružuje mu se svaki dan, u rasponu od statičnih s minimalnom podrškom za interakciju do dinamičkih koji zahtijevaju veliku količinu ažurnih podataka za obavljanje svojih funkcija.
Fotografija je ilustrativna. (Foto: Pixabay)
Fotografija je ilustrativna. (Foto: Pixabay)

Autor: Denis Balant, Enej Hudobreznik


Unatoč brzom razvoju tehnologije, glavni jezik za upravljanje relacijskim bazama podataka i dalje je SQL ili strukturirani upitni jezik, koji uz brojne prilagođene izvedenice (PostgreSQL, MySQL...) vuče korijene iz 70-ih godina prošlog stoljeća.

Pisanje SQL upita često se pokaže dosta dugotrajnim poslom, posebno sa složenijim strukturama baza podataka. Umjesto ručnog pisanja upita i pretvorbi u objekte, tipičnih za objektno orijentirane programske jezike, mnogo je prirodnije i često jednostavnije mapirati klase iz izvornog koda u shemu podataka, a ne obrnuto. Time se štedi vrijeme razvoja, a ujedno je puno lakše prepoznati odnose među entitetima. Ova metoda se naziva objektno-relacijsko preslikavanje (ORM).

Za .NET okruženje, Microsoft u tu svrhu nudi Entity Framework Core (skraćeno EF Core) okvir otvorenog koda, koji omogućuje razvoj orijentiran na podatke (pristup Code First), gdje se međusobno povezani podaci jednostavno prikupljaju u klasama koje predstavljaju tablice, a okvir se temelji na njihovoj osnovi, razumije odnose i stvara shemu baze podataka u vlastitom formatu. Najveća prednost ovakvog pristupa je mogućnost instaliranja podatkovne sheme na željenu bazu podataka bez poznavanja SQL-a.

EF Core komunicira s bazama podataka putem biblioteka dodataka koje se nazivaju dobavljači baze podataka, tako da je prebacivanje na drugu bazu podataka jednostavno. Korisnik ih može instalirati putem upravitelja paketa (NuGet za C#). Službene biblioteke dostupne su samo za Microsoftova rješenja SQL Server i Azure Cosmos DB te projekt SQLite, a zahvaljujući snažnoj zajednici otvorenog koda okvir podržava praktički sve glavne relacijske baze podataka (MySQL, PostgreSQL...).

Kao primjer modeliranja podataka pogledajmo tablicu "Student" koja ima atribute ime (niz do dvadeset znakova), prezime (niz do dvadeset znakova) i jedinstveni identifikator (cijeli broj).

Table Student (vlastiti izvor)

U PostgreSQL-u ovu tablicu definiramo na sljedeći način:

Definicija tablice učenika u PostgreSQL (vlastiti izvor)

Uz definicije osnovnih tipova za ime i prezime, također zahtijevamo da nikada nisu prazni (NOT NULL). Tip SERIAL predstavlja jedinstveni cijeli broj, koji u našem slučaju služi kao primarni ključ ID-a. Za svaki dodani entitet automatski se određuje na temelju ID-a prethodno dodanog identiteta koji se jednostavno povećava.

Međutim, puno je lakše definirati tablicu kao klasu u izvornom kodu logike aplikacije pomoću ORM-a koji sam stvara objekt i odgovarajuće zahtjeve baze podataka. Oznaka Key iznad atributa klase označava primarni ključ, a Required označava da atribut ne smije biti prazan.

Nakon razvoja, okvir EF Core omogućuje nam da automatski generiramo shemu podataka iz koda i implementiramo je u odabranu bazu podataka putem alata naredbenog retka koji su uključeni u okvir. Kroz ove migracije upravlja se postupnim promjenama sheme baze podataka, koje osiguravaju da baza podataka ostane sinkronizirana s podatkovnim modelom aplikacije. Nove migracije, koje su pohranjene u obliku posebnih klasa u EF Core, kreiraju se usporedbom trenutnog podatkovnog modela s trenutnom shemom baze podataka (stanje zadnje migracije).

Definicija tablice učenika pomoću EF Core u .NET okruženju (vlastiti izvor)

Veza s bazom podataka apstrahirana je klasom koja nasljeđuje od klase DbContext. Njegovi atributi su zbirke entiteta tipa DbSet koji se mapiraju u tablice.

Definirana klasa veze s bazom podataka i tablica učenika (vlastiti izvor)

Navedeni okvir za pisanje upita koristi sintaksu LINQ, koja predstavlja objedinjeni način dohvaćanja i obrade podataka iz različitih izvora. Upit se zatim prevodi u SQL, a sam rezultat se prevodi natrag u objekt, njegov atribut ili tablicu objekata.

Primjer u nastavku prikazuje upit za studenta s poznatim upisnim brojem. Dovoljan je samo jedan poziv metode Find s vrijednošću primarnog ključa (ID).

Primjer studentskog upita s EF Core (vlastiti izvor)

Ako želimo postići isti rezultat bez korištenja ORM alata, potrebno je znatno više koda. Prikazan je primjer korištenja biblioteke NpgSql. Prvo moramo kreirati objekte koji predstavljaju SQL upit i čitati bazu podataka, pri čemu moramo paziti da ispravno uključimo parametar kako bismo izbjegli moguće ranjivosti, kao što je npr. SQL injekcija. Ovaj put moramo sami kreirati studentski objekt, ali moramo paziti na redoslijed atributa u upitu i mogućnost greške u upitu.

Primjer studentskog upita korištenjem biblioteke NpgSql (vlastiti izvor)
Odgovor na gornji upit (vlastiti izvor)

Objektno-relacijsko preslikavanje nam tako nudi sloj apstrakcije koji značajno ubrzava razvoj softvera zbog preslikavanja iz objektno orijentiranog razvojnog plana, jer SQL kod ne treba pisati odvojeno od izvornog (često objektno orijentiranog) koda, dobro napisan ORM podržava dobre razvojne obrasce i prakse za dizajn aplikacija, dok omogućuje ne-SQL programerima da lakše integriraju relacijsku bazu podataka u svoju aplikaciju.

Međutim, važno je naglasiti da ORM nije savršeno rješenje. Slabost je upravo u apstrakciji koju nam nudi. Generira značajno više SQL koda nego što bi programer napisao, što može uvelike utjecati na brzinu aplikacije, može sakriti loše prakse pristupa bazi podataka i predstavlja problem kompatibilnosti s prethodnim verzijama. Iako je generirani kod u većini slučajeva ispravan, preporuča se da ga provjerite i testirate ručno.

Objektno relacijsko preslikavanje je funkcionalnost koja nije izvorna za .NET okruženje. Funkcionalnost pruža većina okvira i biblioteka za različite jezike. Primjeri su Django za Python, Gorm za Go, Spring za Javu, Prisma za JavaScript (ili Node.js)...




Što drugi čitaju?