LINQ – VI DIO LINQ TO SQL


…nastavak prethodnog posta

DB Model

Nakon uspješno izvedenog tutorijala pokušat ću objasniti način na koji radi LINQ to SQL.

Prva stvar koji smo uradili bila je formiranje modela DB. Procedura se ništa ne razlikuje od one kojom formiramo novu formu ili neku kontrolu. Kada smo formirali LINQ to SQL datoteku, VS dizajner je prikazao prazan model, koji se sastoji od dva podjeljena prozora lijevi prozor u kojem modeliramo klase odnosno entitete, a u drugi desni importujemo funkcije i storne procedure. Funkcija modela baze podataka je mapiranje prvenstveno tabela iz DB, koje u .NET nazivamo klasama ili entitetima. Svaki entitet je mapirana tabela, čije osobine (Properties) mapiraju kolone iz dotične tabele. I na kraju svaka instanca klase je jedan red (vrsta) tabele DB-a.

lintosql15

Razlika izmedju dizajnera DataSeta i LINQ to SQL je ta što u ovom drugom slučaji ne specificiramo SQL upit prilikom formiranja klase odnosno entiteta tabele. U tutorijalu smo vidjeli jedan od načina mapiranja tabele, gdje nam dizajner VS preko modela generiše izvorni kod. Na sljedećoj slici prikazan model baze podataka sa klasom Customers.

lintosql16

Analizirajmo izvorni kod koji je generirao VS. Sljedeća slika pokazuje generirani izvorni kod. Primjetićemo da je VS generirao dvije klase i to:

· NorthWindKlaseDataContext

· Customers

Customers klasa je mapirana tabela Customers baze podataka, dok druga NorthWindDataContext koja klasa obavlja transakcija izmedju klijenta i servera. O DataContext klasi biće riječi kasnije.

lintosql17

Primjetićemo da iznad klase Customers se nalazi Atribut Table koji posjeduje jedan argument i to naziv tabele iz DB. Ovim atributom korespodentna klasa se označava kao klasa generirana prilikom mapiranja tabele iz DB. Ako se naziv klase podudara sa nazivom tabele u DB, kompajler je dovoljno „pametan“ da izvrši mapiranje sa tabelom i bez pomenutog atributa. Isti je slučaj i sa DataContextom.

Implementacija klase Customers je vrlo jednostavna i sastoji se od implementacije osobina (Properties) klase, koje odgovaraju kolonama tabele Customers. Naravno, imamo mogućnost da dodajemo nove osobine (Properties) samo klasi u glavno ako želimo na novou aplikacije da dodajemo dodatne kolone u vidu prekalkulisanih kolona i sl.

Klasa pored spomenutog posjeduje i nekoliko parcijalnih metoda (Partial methods o kojim sam pisao ranije) metode koje se implementiraju po potrebi. Sve osobine klase mogu se pregleavati i u dizajnerskom modulu odnosno podešavati po potrebi.

Osobine klase Customers

Atribute tabele koristimo prilikom formiranja klase (entiteta) u modelu koja korespondira tabeli u DB. Atribute možemo podešavati kako iz dizajnera tako i kroz izvorni kod. Sljedeća slika nam prikazjuje osobine klase Customers, koje većom predstavljaju atribute tebele. Možemo primjeti da postoji samo jedan atribut kojeg možemo promijeniti, a to je naziv (Name) entiteta.

clip_image036

Atribute tabele dobijamo kada desnim klikom iz kontekstnog menija izaberemo opciju Properties.

Osobine članova klase Customers

Svaka generirana klasa posjeduje osobone koje korespondiraju kolonama tabele DB. Na sljedećoj slici su prikazane osobine članova klase, koje u većem broju predstavljaju i same atribute kolona.

clip_image038

Osobine koje predstavljaju i atribute kolona prikazani su masnim fontom.

· Access – identifikator pristupa članu u klasi

· Auto Generated Value (IsDbGenerated)- indikator da se osobina klase (kolona tabele) generira i DB. Ovo uglavnom posjeduju kolone koje su primarni ključevi tabela, a imaju osobinu autogeneriranja vrijednosti. Ako je to slučaj onda pored true vrijednosti ovog atributa, atribut DBType mora imati IDENTITY() oznaku.

· Auto-Sync (AutoSync) – Određuje način sihronizacije kolone (člana klase) nakon što se izvrši upit Insert ili Update. Moguće vrijednosti su: OnInsert – sihroniziraj kada se desi Insert upit, OnUpdate – sihroniziraj kada se desi Update upit, Always – uvijek sihroniziraj vrijednost kolone, Never – nema sihronizacije.

· Delay Loaded – Određuje način učitavanja kolone iz DB prilikom privog pristupa DB. Ovu osobinu korisno je koristiti za BLOB kolone koje sadrže slike ili neke druge velike podatke u koloni. Ova osobina nam omogućava da se vrijednost kolone učitava samo u onom trenutku kada je to zaista potrebno.

· Inheritance Modifer – identifikator preklapanja člana klase.

· Name – naziv člana

· Nullable (CanBeNull) – identifikator stanja vrijednosti. Da li korespodentna kolona može sadržavati NULL vrijednost.

· Pripary Key (IsPrimaryKey) – oznaka kolone da li reprezentira primarni ključ.

· Read Only – identifikator da li član može biti promjenjen.

· Server Data Type – Tip podatka kolone koja je definisana u DB.

· Source (Storage)- Naziv varijable u kojoj se pohranjuju vrijednosti.

· Time Stamp – da li je kolona označena kao TimeStamp.

· Type (DBType)– tip podatka člana.

· UpdateCheck (UpdateCheck) – određuje način na koji LINQ to SQL definiše optimistic concurrency konflikte u DB.Moguće vrijednosti: Always– uvijek koristi kolonu za detekciju konflikta u BD, Never: nekoristi kolonu za detekciju konflikta, WhenChanged : koristi kolonu samo kad je član klase (Entiteta)promjenjen.

Primjer manipulacije tabele Customers pomoću LINQ

Kroz naredni primjer vidjećemo kako koristiti razne LINQ operatore prilikom izvlačenja informacija iz DB. Više informacija o operatorima u LINQ možete naći u pretodnom postu o LINQ. Za ovaj tutorijal slično kao u prethodnom primjeru formirajte Windows Forms C# aplikaciju, te formirajte model DB i mapirajte Tebelu Customers. U Form1 formirajte dataGridView kontrolu i povežite je sa modelom slično kao i u prethodnom slučaju.

Primjer 1. Za privi primjer pokušat ćemo izdvojiti sve partnere čije je sjedište u Londonu. Naš LINQ upit za ovaj slučaj prikazan je na sljedećoj slici.

clip_image040

Poslije pokretanja aplikacije rezulat bi trebao biti kao na sljedečoj slici:

lintosql21

Primjer 2: Potrebno je grupirati sve poslovne partner po gradovima, te u drugoj koloni prikazati broj partnera za svaki grad. LINQ upit za ovaj primjer prikazan je na sljedećoj slici:

clip_image044

Manipulacija nad Master/Detail relacijama

Kako je već kazano LINQ to SQL u potpunosti podržava relacije između tabela u DB. Čak šta više kada je definisana relacija izmedju klasa (entiteta) u dizajneru nije potrebno posebno definisanje relacija (u vidu JOIN naredbe). Ako mapiramo tabele Customers i Orders u dizajner kao na sljedećoj slici možemo primjetiti da se formirala relacija medju njima automatski.

clip_image046

To znači da je dizajner pored mapiranja tabela mapirao i relaciju madju njima jer je ona definisana u DB. Naravno, relaciju medju klasama možemo definisati i ručno. To radimo ako iz ToolBoxa povučemo stavku Asocciationclip_image048.

Ako kliknemo desnom tipkom miša na relaciju i izaberemo opciju Preperties u Property prozoru dostupne su nam osobine relacije.

clip_image050

· Cardinality – vrsta relacije

· Child Property – osobine tabele potomka

· Parent Property – osobine tabele roditelja

· Participating Property – detalji relacije medju tabelama

· Unique – jedinstvenost vanjskog ključa

Primjer manipulacije nad tabelama u Master/Detal relaciji

Koristeći prethodni primjer i dizajner kojeg smo upravo kreirali napravićemo nekoliko primjera svojstvenih ovakvoj zavisnosti medju tabelama.

Primjer 1. Izvucimo sve narudžbe kupaca iz Londona.

Za ovaj primjer LINQ upit izgleda kao na sljedećoj slici.

clip_image052

Ako prokrenemo aplikaciju rezulat dobijamo kao na sljedećoj slici.

lintosql27

Iz ovog primjera vidimo da ako želimo da izvlačimo podatke iz dvije zavisne tabele, dovoljno je da kod deklarisanja klasa definišemo relaciju izmedju njih, a LINQ upite konstruišemo bez naredbe JOIN. Ovo je jeddna od najvažnijih osobina LINQ to SQL. Klasa Order u prethodnom primjeru već ima u sebi sadržave sve kupce (Customers). Najinteresantnije je da se pogleda Log od DataContexta i vidi na koji način se SQL string prosljedio SQL Serveru. Donja slika pokazuje SQL upit koji je prosljeđen SQL Serveru baziran na našem zadnjem primjeru LINQ.

Da bi prikazali u U otput Window SQL koji se prosljedjiva SQL Serveru potrebno je komande iz DataContext – a poslati u Output preko:

clip_image056

Naravno oni koji posjeduju SQL Server mogu pokrenuti profiler i pogledati SQL upite koji dolaze.

clip_image058

Sa slike se vidi da je SQL upit koji je generiran u sebi sadrži SQL komande spajanja (JOIN). Ista situacija se dešava ako povežemo nekoliko tabela hiearhijski u Master/Detail relacije.

Nastavlja se…….

About Bahrudin Hrnjica

PhD in Mechanical Engineering, Microsoft MVP for .NET. Likes .NET, Math, Mechanical Engineering, Evolutionary Algorithms, Blogging.

Posted on 07/12/2007, in .NET, C# and tagged . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s