[.NET] Relationele DB i.c.m. ADO.NET

Pagina: 1
Acties:
  • 1.064 views sinds 30-01-2008
  • Reageer

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
Ik heb een relationeel opgezet databasemodel wat gekoppeld zit aan een ASP.NET C# project. Alles goed en aardig; ik kan prima met behulp van datatables/-adapters gegevens in en uit de tabellen halen. Maar wat nu wanneer ik informatie wil gaan combineren?

Bijvoorbeeld: ik heb een tabel met de gebruikers, en die zitten allemaal op één bepaalde afdeling. Oftewel: een veld van de gebruikerstabel verwijst naar een record in een "afdelingen" tabel. Nu wil ik in mijn "afdelingen" overzicht graag laten zien hoeveel gebruikers er in de verschillende afdelingen zitten. Ik weet hoe ik dat in SQL doe, ik krijg het ook wel in m'n code gepropt; maar ik wil graag weten wat de "way to go" is: hoe doe je dat netjes en gestructureerd??

Overigens gebruik ik een 3-tier opzet met DAL vanuit visual studio, eigen gemaakte BLL classes en een ASP.NET interface laag.

Een vraag die hierop aansluit: waar definieer ik dan een structuur waarin de velden uit mijn "afdelingen" tabel zitten, aangevuld met een "aantal werknemers" veld waarin het totaal staat?

[ Voor 9% gewijzigd door jsiegmund op 13-12-2006 16:05 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 18:04
Maak in je datalaag in de juiste class een method 'GetNumberOfUsersInDepartement' oid, die gewoon een scalar SQL statement uitvoert, en het resultaat returned.

DataSets/DataTables zijn in bepaalde gevallen wel handig, maar je moet ze ook niet gebruiken om te gebruiken.

Trouwens the way to go bestaat niet. Er zijn altijd verschillende wegen die naar Rome leiden, en de een is daarom niet slechter of beter dan de andere. Alles hangt af van de context.

[ Voor 26% gewijzigd door whoami op 13-12-2006 16:41 ]

https://fgheysels.github.io/


  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
Okay, tot zover is het duidelijk. En uiteraard natuurlijk niet the way maar wel een weg die een beetje direct naar Rome loopt en niet via Japan ofzo ;)

Goed, nu heb ik dan de gegevens: het totaal aantal gebruikers, maar hoe krijg ik die nu op een aardige manier afgebeeld in bijvoorbeeld een gridview op het scherm?

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
Een aanvullende vraag over hetzelfde onderwerp:

om mijn gebruikers te valideren maak ik gebruik van de locale LDAP server. Ik heb echter wat extra gegevens van de gebruiker nodig, dus heb ik een eigen tabel die via de ProviderUserKey mapt naar de gebruikers in de LDAP. Op die manier kan ik wat meer gegevens opslaan en staan die gegevens in relatie met de gebruikers in de LDAP.

Nu kan ik met Membership.GetUsers() prima alle gebruikers opvragen; en met een query de velden uit mijn tabel. Maar hoe combineer ik die 2 nu in één gridview, zodat achter de gebruiker/email uit de LDAP nog wat velden uit mijn eigen tabel staan?

  • Mastermind
  • Registratie: Februari 2000
  • Laatst online: 29-11 15:35
Een template column maken met een label, bijvoorbeeld lblOpmerking.Bij de OnRowDataBound van de grid kun je deze label.Text zetten met wat je wilt. Een Template Column maak je in de Column Collection van de GridView.
Je moet natuurlijk informatie hebben welk veld uit de tabel hij moet ophalen. Daarvoor heb je een relatie tussen de tabellen nodig. Om de PrimaryKey te weten, moet je de DataKey zetten op de PK van de hoofdtabel waarin je bind (we noemen deze Gebruikers).
Stel de PK van je tabel is GebruikersID, dan moet je deze invullen bij DataKey in de GridView properties.

Dan krijg je iets als:
C#:
1
2
3
4
5
6
7
8
9
10
11
protected void gvGebruikers_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Vind de Primary Key van de Row
     int GebruikersID = (int)((GridView)sender).DataKeys[e.Row.RowIndex].Value;
// Vind de Label
    Label lblOpmerking = (Label)e.Row.FindControl("lblOpmerking");
// Doe een INNER JOIN met jouw 2e tabel met de PK/FK relatie, met LLBLGEN is dit:
   string opmerking = Gebruikers.TweedeTabel.Opmerking;
// Daarna:
    lblOpmerking.Text = opmerking;
}

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 09:27

mulder

ik spuug op het trottoir

Mastermind schreef op donderdag 14 december 2006 @ 14:35:
Een template column maken met een label, bijvoorbeeld lblOpmerking.Bij de OnRowDataBound van de grid kun je deze label.Text zetten met wat je wilt. Een Template Column maak je in de Column Collection van de GridView.
Je moet natuurlijk informatie hebben welk veld uit de tabel hij moet ophalen. Daarvoor heb je een relatie tussen de tabellen nodig. Om de PrimaryKey te weten, moet je de DataKey zetten op de PK van de hoofdtabel waarin je bind (we noemen deze Gebruikers).
Stel de PK van je tabel is GebruikersID, dan moet je deze invullen bij DataKey in de GridView properties.

Dan krijg je iets als:
C#:
1
2
3
4
5
6
7
8
9
10
11
protected void gvGebruikers_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Vind de Primary Key van de Row
     int GebruikersID = (int)((GridView)sender).DataKeys[e.Row.RowIndex].Value;
// Vind de Label
    Label lblOpmerking = (Label)e.Row.FindControl("lblOpmerking");
// Doe een INNER JOIN met jouw 2e tabel met de PK/FK relatie, met LLBLGEN is dit:
   string opmerking = Gebruikers.TweedeTabel.Opmerking;
// Daarna:
    lblOpmerking.Text = opmerking;
}
Beetje Slow & Dirty dit. Ik zou er voor zorgen dat de BLL al een correct view aflevert (een collectie van je objectType)

oogjes open, snaveltjes dicht


  • Mastermind
  • Registratie: Februari 2000
  • Laatst online: 29-11 15:35
Het is beter door een View te maken in de database inderdaad. Zo doe ik dat ook altijd.

Maar dat was zijn vraag niet. Zijn vraag was: Hoe voeg ik aan de GridView velden van een eigen tabel toe, en daar heb ik antwoord op gegeven.

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
Ik heb het inmiddels opgelost door een extra klasse aan te maken met de juiste properties, en die klasse te gebruiken als dataset. Daarvan een List gebakken die wordt teruggegeven uit de BLL; meteen de juiste gridview op deze manier.

Zitten hier nog nadelen aan?

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
Hmmm, paar stapjes verder in het ontwerp en ik heb toch regelmatig met dit soort dingen te maken. Dat zou betekenen dat ik iedere keer een nieuwe datatable moet maken voor elke situatie waarin dit voorkomt. Een tijdrovend werkje wat tevens de structuur van de applicatie niet echt ten goede komt (mijns inziens). Een andere methode is bij het binden van de data een functie aan te roepen die die juiste naam uit de database trekt en weergeeft inplaats van de bijbehorende ID. Meningen hierover?

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Wat ik niet begrijp is waarom je zoveel tijd steekt in het opnieuw uitvinden van het wiel? Je hoeft mijn werk niet te kopen, je kunt ook een open source o/r mapper gebruiken, maar hoe dan ook: begrijp dat wat je aan het bouwen bent al door veel mensen opgelost is op een manier die jou in staat stelt om je te richten op je applicatie ipv hoe je welke data nu precies uit de db trekt.

[ Voor 62% gewijzigd door EfBe op 18-12-2006 13:01 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • D-Raven
  • Registratie: November 2001
  • Laatst online: 16-10 10:47
Je hoeft niet per see een eigen klasse te gebruiken om je view te vullen. Je kunt ook de structuur vastleggen in een DataSet en deze laten retourneren door je Business klasse.

Dus dat je een functie maakt bij je Business klasse welke een DataSet teruggeeft waar de gewenste structuur al inzit.

Wat eigenlijk mooier zou zijn is als je een Service klasse hebt welke een methode heeft die daarvoor zorgt. Je wilt namelijk presentatie zoveel mogelijk van je Business model gescheiden houden.

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
EfBe schreef op maandag 18 december 2006 @ 12:55:
Wat ik niet begrijp is waarom je zoveel tijd steekt in het opnieuw uitvinden van het wiel? Je hoeft mijn werk niet te kopen, je kunt ook een open source o/r mapper gebruiken, maar hoe dan ook: begrijp dat wat je aan het bouwen bent al door veel mensen opgelost is op een manier die jou in staat stelt om je te richten op je applicatie ipv hoe je welke data nu precies uit de db trekt.
Wat bedoel je precies? Wat ik probeer is een aardig applicatie ontwerp op te zetten. Ik heb een hoop ervaring met PHP maar nog weinig met ASP.NET; en de aanpak is daar toch net even wat anders. Vandaar dat ik dus aan het zoeken ben naar een nette en handige opzet van je applicatie. Hoe je dat zou moeten kopen snap ik niet, tenzij jij cursussen schrijft ofzo.

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:04
EfBe heeft het over het kopen van een O/R mapper. Da's een tool zoals NHibernate of LLBLGen die -simpelgezegd- je objectmodel mapt naar je relationeel DB model.

https://fgheysels.github.io/


  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
Ah okee, ik had z'n sig. helemaal niet gezien dus ik snapte het al niet. Inderdaad wellicht handig zo'n tool, hoewel ik qua prijs dan eerder naar de opsource varianten zal kijken ;) Zal het demootje sowieso eens een kans geven.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
iCe01 schreef op maandag 18 december 2006 @ 16:27:
Ah okee, ik had z'n sig. helemaal niet gezien dus ik snapte het al niet. Inderdaad wellicht handig zo'n tool, hoewel ik qua prijs dan eerder naar de opsource varianten zal kijken ;) Zal het demootje sowieso eens een kans geven.
Als prijs een factor is, dan is jouw tijd dat wellicht ook. ;) Maar er zijn open source / gratis o/r mappers die ook ervoor zorgen dat je niet meer met data-access plumbing bezig bent. Zoals gezegd: zolang je maar inziet dat opnieuw het wiel uitvinden niet echt nuttige tijdsbesteding is anders dan het voeden van interesse.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 15:29
Ok, die boodschap is nu inderdaad duidelijk. Zal eens rondneuzen wat er zoal te vinden is op dat gebied. Ook wel handig dat ik nu in ieder geval weet hoe het beestje heet, dat zoekt wat handiger.

Verwijderd

whoami schreef op maandag 18 december 2006 @ 16:22:
EfBe heeft het over het kopen van een O/R mapper. Da's een tool zoals NHibernate of LLBLGen die -simpelgezegd- je objectmodel mapt naar je relationeel DB model.
Ik was op zoek naar een verklarende uitleg over Datasets en Object Relational Mapping en kwam via Google op dit forum terecht, bij een oude uiteenzetting en interessante discussie:

\[C#] Multi-tier applicatie

Ik heb hier een en ander opgestoken, vooral qua gebruik van de dataset, zeer goede argumenten voor en tegen. Datasets kende ik al een beetje vermits ik er in VS 2005 al wat mee gewerkt heb. Van ORM had ik tot voor kort nog niet gehoord (ja ik ben nog maar een beginner), maar het lijkt mij dat dit de aangewezen tool is om concurrencyproblemen aan te pakken en SQL in de code te vermijden? Of om een db ten allen tijde persistent te houden? Ik heb nog wat op internet rondgesurft maar zie ff het bos door de bomen niet meer.

Wat zijn nu de voor- en/of nadelen van ORM en wanneer moet ik ORM ipv datasets (in een multi-user omgeving) gebruiken? Enige verduidelijking is zeer welkom!

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:04
Een O/R mapper zal afaik geen concurrency problemen aanpakken.
SQL in de code vermijden kan wel, aangezien die O/R mapper zorgt voor de Data Access. Dat wil echter nog altijd niet zeggen dat je, als je gebruik maakt van een o/r mapper, je zowiezo een 'meerlagenmodel' gebruikt.
Of om een db ten allen tijde persistent te houden?
Wat bedoel je hier precies ? Je bedoelt consistent ? Tja, ik vraag me af of dit echt iets is wat je als voordeel van een o/r mapper kunt toewijzen.

O/R mapping is niet echt een vervanging voor datasets. Als je custom business classes gebruikt (dus zelf geschreven classes die bv een persoon, een order, etc... voorstellen) ipv datasets, dan kan een O/R mapper zoals NHibernate je heel wat werk besparen.
Andere O/R mappers, zoals LLBLGen, genereert zelf de business-classes.

https://fgheysels.github.io/


Verwijderd

whoami schreef op zondag 07 januari 2007 @ 19:08:
Wat bedoel je hier precies ? Je bedoelt consistent ? Tja, ik vraag me af of dit echt iets is wat je als voordeel van een o/r mapper kunt toewijzen.
Ja, het feit dat de data in de db ten allen tijde correct is bedoel ik.
Hierop verder gaand: werken met datasets maakt dat je niet geconnecteerd werkt, en pas wanneer je update ga je daadwerkelijk de wijzigingen wegschrijven (als een andere user ondertussen die data niet bewerkt heeft tenminste). Bij een ORM zijn,als ik het goed begrepen heb, de objecten in synchronisatie met de db, klopt dat? Dus op die manier kan je dan vermijden dat er veel tijd wordt gestoken in aanpassingen die achteraf niet doorgevoerd kunnen worden omdat een andere user de data ondertussen heeft bewerkt?

Verder: stel dat ik stored procedures zou schrijven en werk met een dataset, dan vermijd ik ook grote stukken SQL in mijn code, compenseert dit dan niet het voordeel van ORM waar geen SQL nodig is?

Qua performance, stel dat ik in een multi-user omgeving werk waar weinig conflicten op de db zijn, dus de kans dat iemand anders gelijktijdig iets verandert gering is, wat is dan het meest interessante, werken met datasets of ORM?

Kortom, ik vind dit -ook al ben ik nog groen hierin- een interessante materie, en zou graag van een ervaren iemand de pro's en contra's horen van datasets en ORM, wanneer gebruik je het een of het ander, wat zijn de gevaren van beide... ?

Bedankt alvast

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Verwijderd schreef op zondag 07 januari 2007 @ 20:29:
[...]

Ja, het feit dat de data in de db ten allen tijde correct is bedoel ik.
Hierop verder gaand: werken met datasets maakt dat je niet geconnecteerd werkt, en pas wanneer je update ga je daadwerkelijk de wijzigingen wegschrijven (als een andere user ondertussen die data niet bewerkt heeft tenminste). Bij een ORM zijn,als ik het goed begrepen heb, de objecten in synchronisatie met de db, klopt dat? Dus op die manier kan je dan vermijden dat er veel tijd wordt gestoken in aanpassingen die achteraf niet doorgevoerd kunnen worden omdat een andere user de data ondertussen heeft bewerkt?
Hmm, volgens mij haal je een paar dingen door elkaar. ORM staat voor Object-To-Relational mapping, en dat is dan ook precies wat het doet: het vertaalt de records die je uit je relationele database haalt naar (meestal collecties van) objecten, en vice versa kan je middels een method call tegen een object zeggen dat hij zichzelf moet inserten / updaten / deleten in plaats van dat je dit moet regelen middels het uitvoeren van een SQL statement.
Onder water moet dit werk natuurlijk alsnog gebeuren, maar het voordeel is dat je dit niet zelf uit hoeft te programmeren, dit regelt de OR mapper voor je.

De winst bij ORM is dat je een stuk syntactic sugar krijgt waardoor je in je applicatie je data als objecten kan blijven behandelen, zonder dat je zelf de 'paradigm shift' naar het relationele model hoeft te maken (lees: zelf SQL statements hoeft te schrijven, of een rij met een specifieke primary key hoeft te updaten). Vanuit een OO perspectief is dit dus een nettere oplossing.

Echter, als je een OR mapping toepast, zegt dit nog niets over in hoeverre de data in je applicatie overeenkomt met de data in je database. OR-mappers als NHibernate laten je (voor zover ik weet) vrij in de keuze of je wel of geen chaching, lazy loading en/of delayed writing gebruikt.
Vanuit een performance perspectief is dit waarschijnlijk wel aan te raden (omdat je waarschijnlijk minder roundtrips naar de DB nodig hebt), maar je zult merken dat je donders goed in de gaten moet houden welke data wel, en welke data niet verouderd mag zijn. Als dit erg complex wordt, dan kan dat een argument zijn om deze performance-optimalisaties niet toe te passen, zodat je minder je hoofd hoeft te breken of je wel met (redelijk) actuele data werkt.

Andersom is een DataSet ook niet inherent aan "problemen met verouderde data". Je kunt er nl. voor kiezen om een DataSet elke keer opnieuw in te lezen als je de betreffende data nodig hebt, en na elke wijziging op een DataSet deze meteen te laten doorvoeren op de database.

De reden dat de DataSet vaak in 1 adem genoemd wordt met het risico op verouderde data, is (volgens mij) dat de DataSet gebaseerd is op de filosofie van "minimaliseer het aantal roundtrips naar de DB", en niet "houd de data in code zo consistent mogelijk met die in de DB". En dan is het risico op verouderde data meer aanwezig.
Verder: stel dat ik stored procedures zou schrijven en werk met een dataset, dan vermijd ik ook grote stukken SQL in mijn code, compenseert dit dan niet het voordeel van ORM waar geen SQL nodig is?
Ja en nee. Ja, het is beter om geen SQL in je business logic te gebruiken, en het is sowiezo een goed idee om stored procedures te gebruiken (de DB kan SP's doorgaans sneller uitvoeren dan losse SQL statements). Dit kan je zowel met de combinatie DataSets + SPs als met een OR mapping bereiken, dus daar zit het verschil niet echt.
De echte winst van een OR mapping is (zoals hierboven al vermeld) dat je in je applicatie je data als objecten kan behandelen in plaats van als rijen uit een tabel.
Qua performance, stel dat ik in een multi-user omgeving werk waar weinig conflicten op de db zijn, dus de kans dat iemand anders gelijktijdig iets verandert gering is, wat is dan het meest interessante, werken met datasets of ORM?
Je hebt nu inmiddels denk ik wel door dat je vraag zou moeten zijn: "Gebruik ik wel of geen lazy loading en/of delayed writing?". ;)
Wat meespeelt in deze beslissing is:
- Hoeveel conflicten met verouderde data denk je tegen te komen? (zoals je al aangaf)
- In hoeverre heb je de performancewinst van lazy loading en delayed writing nodig?
- Welke data denk je veilig te kunnen cachen zonder in de problemen te komen?

--toevoeging:--
Het gebruik van de concepten "lazy loading" (data pas inlezen als je het echt nodig hebt) en "delayed writing" (wijzigingen opsparen en dan als een bulk-opdracht naar de DB versturen) is meestal geen kwestie van wel of niet gebruiken, het is een spectrum.

De extreemste vormen zijn:
- altijd lazy loading (m.a.w. nooit geen data cachen)
- nooit lazy loading (alles van tevoren uitlezen en naar de client toetrekken (!!))
- alles delayed writen (bij het afsluiten van de applicatie pas DB-updates doen)
- nooit delayed writen (bij het aanpassen van een enkel veld meteen een update doen).

Het moge duidelijk zijn dat (heel misschien met uitzondering van het 1e punt) dit geen werkbare oplossingen zijn. Een praktische oplossing ligt dus ergens in het midden, maar waar... dat verschilt per applicatie. :)

[ Voor 8% gewijzigd door MrBucket op 07-01-2007 21:41 ]


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

MrBucket schreef op zondag 07 januari 2007 @ 21:25:
en het is sowiezo een goed idee om stored procedures te gebruiken (de DB kan SP's doorgaans sneller uitvoeren dan losse SQL statements).
Sorry, ik kan 'm niet laten. Het is lang niet altijd zo, en SP's leveren vooral veel overhead op. Het antwoord op de vraag of je SP's moet gebruiken is: het hangt ervan af. Dat SP's (doorgaans) beter zijn is een fabel.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
kenneth schreef op zondag 07 januari 2007 @ 22:41:
[...]
Sorry, ik kan 'm niet laten. Het is lang niet altijd zo, en SP's leveren vooral veel overhead op. Het antwoord op de vraag of je SP's moet gebruiken is: het hangt ervan af. Dat SP's (doorgaans) beter zijn is een fabel.
Hey, het is niet voor niets een discussieforum :)

Kan je een aantal nadelen noemen? Lijkt me zeker relevant voor dit topic, en ik ben zelf ook wel benieuwd eigenlijk.

Verwijderd

MrBucket schreef op zondag 07 januari 2007 @ 22:56:
[...]

Hey, het is niet voor niets een discussieforum :)

Kan je een aantal nadelen noemen? Lijkt me zeker relevant voor dit topic, en ik ben zelf ook wel benieuwd eigenlijk.
Thanks voor de verhelderende uitleg, het is me al een heel stuk duidelijker :-)

Betreft nog de concurrency, mag ik dan aannemen dat noch datasets, noch ORM de situatie kunnen vermijden dat wanneer user A iets aan het veranderen is en user B hetzelfde verandert maar sneller klaar is dan A, dat nadien user A een conflict krijgt? Er is dus geen van de twee die eigenlijk op dit vlak beter is dan de andere, of ben ik verkeerd? Ik meen ergens gelezen te hebben dat bij datasets in geval van een conflict de rollback al eens durft misgaan, met inconsistente data in de db tot gevolg, of is dit een fabeltje? Het enige wat men kan doen is om ten gepasten tijde -afhankelijk van de situatie zoals je aanhaalt- de data zelf te updaten naar de db en opnieuw op te halen?

Ik ga eens een klein progje in C# maken waarin ik een ORM ga gebruiken, welke object relational mapper raden jullie zoal aan?

ps de discussie over stored procedures volg ik graag verder ;-)

Verwijderd

SP's kunnen soms een spectaculaire prestatiewinst opleveren, maar bij 'plain vanilla' queries (95% van de queries in een normale applicatie) win je er nauwelijks iets mee.
Naast voordeel is een groot nadeel van SP's, dat ze zich in de database bevinden, en niet in de applicatie. Stel (praktijkvoorbeeld) je brengt een update van je applicatie uit, incl. gewijzigde SP's. Na een tijdje besluit een systeembeheerder om een oude backup van de database terug te zetten. Gevolg: de SP's corresponderen niet meer met de applicatie, met allerlei vage fouten van dien. Dit voorkom je door de queries in de data access layer van je applicatie op te nemen.

Overigens staat optimistic of pessimistic locking los van het feit of je datasets of een O/R mapper gebruikt, maar dat was met andere woorden al gezegd.

Verwijderd

NHibernate is een leuke ORM, maar nogal lomp. Maar ja, dat is m.i. een SqlDataAdapter ook. Een SqlDataReader is een stuk slanker, en performt een stuk beter, maar dan moet je zelf in je DAL ietsje meer werk doen om de boel om te zetten naar een objectstructuur. Maar dat is goed te doen.

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 18:39

gorgi_19

Kruimeltjes zijn weer op :9

Verwijderd schreef op maandag 08 januari 2007 @ 00:08:
SP's kunnen soms een spectaculaire prestatiewinst opleveren, maar bij 'plain vanilla' queries (95% van de queries in een normale applicatie) win je er nauwelijks iets mee.
Met parametrized queries is je snelheidswinst in die gevallen ook 0 (enige verschil is de hoeveelheid bytes die je de interne lijn overstuurt van het SQL statment zelf) :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 18:04
MrBucket schreef op zondag 07 januari 2007 @ 22:56:
[...]

Hey, het is niet voor niets een discussieforum :)

Kan je een aantal nadelen noemen? Lijkt me zeker relevant voor dit topic, en ik ben zelf ook wel benieuwd eigenlijk.
Dat is een andere discussie waar je hier in PRG (en op andere fora) zeker een aantal topics zult over vinden. :) Het is trouwens een discussie die al jaaaaren aan de gang is

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 18:04
Verwijderd schreef op maandag 08 januari 2007 @ 00:20:
NHibernate is een leuke ORM, maar nogal lomp. Maar ja, dat is m.i. een SqlDataAdapter ook. Een SqlDataReader is een stuk slanker, en performt een stuk beter, maar dan moet je zelf in je DAL ietsje meer werk doen om de boel om te zetten naar een objectstructuur. Maar dat is goed te doen.
IMHO vergelijk je hier appels en peren. NHibernate is een O/R mapper, maar een DataAdapter niet. Een DataReader wordt trouwens door een DataAdapter gebruikt om een dataset op te vullen. En ja, een DataReader is sneller, maar dat wil dan ook niet zeggen dat je altijd een DataReader moet gebruiken. Gebruik gewoon hetgeen het beste past voor een bepaalde situatie.

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op zondag 07 januari 2007 @ 23:27:
[...]

Betreft nog de concurrency, mag ik dan aannemen dat noch datasets, noch ORM de situatie kunnen vermijden dat wanneer user A iets aan het veranderen is en user B hetzelfde verandert maar sneller klaar is dan A, dat nadien user A een conflict krijgt? Er is dus geen van de twee die eigenlijk op dit vlak beter is dan de andere, of ben ik verkeerd? Ik meen ergens gelezen te hebben dat bij datasets in geval van een conflict de rollback al eens durft misgaan, met inconsistente data in de db tot gevolg, of is dit een fabeltje? Het enige wat men kan doen is om ten gepasten tijde -afhankelijk van de situatie zoals je aanhaalt- de data zelf te updaten naar de db en opnieuw op te halen?
Er is geen oplossing voor. Zie:
http://weblogs.asp.net/fbouma/archive/2003/05/24/7499.aspx

Veel O/R mappers hebben 1 concurrency methodiek (optimistic), anderen laten je vrij of hebben een plugin-architectuur waarbij je je concurrency methodiek per context/entity kunt aanpassen (LLBLGen Pro)
MrBucket schreef op zondag 07 januari 2007 @ 21:25:
Hmm, volgens mij haal je een paar dingen door elkaar. ORM staat voor Object-To-Relational mapping, en dat is dan ook precies wat het doet: het vertaalt de records die je uit je relationele database haalt naar (meestal collecties van) objecten, en vice versa kan je middels een method call tegen een object zeggen dat hij zichzelf moet inserten / updaten / deleten in plaats van dat je dit moet regelen middels het uitvoeren van een SQL statement.
Beetje kort door de bocht, want wat jij omschrijft is EEN implementatie van een O/R mapper. ORM staat voor Object Role Modelling overigens (http://www.orm.net) en wordt veelvuldig gebruikt om O/R mapper/mapping aan te duiden, maar dat is onjuist.

O/R mapping zorgt ervoor dat 2 verschillende paradigmas (OO vs Relational) in 1 applicatie kunnen worden gebruikt zonder dat je de een aan de ander hoeft aan te passen. Dus je hoeft niet je entity classes aan te passen aan de tables en vice versa.

Zie: http://weblogs.asp.net/fbouma/archive/2004/10/09/240225.aspx
Echter, als je een OR mapping toepast, zegt dit nog niets over in hoeverre de data in je applicatie overeenkomt met de data in je database. OR-mappers als NHibernate laten je (voor zover ik weet) vrij in de keuze of je wel of geen chaching, lazy loading en/of delayed writing gebruikt.
Dat is niet iets wat gerelateerd is aan een O/R mapper: alle data die jij leest uit een DB is vanaf dat moment 'Stale', m.a.w: je kunt wel net doen alsof de data in memory dezelfde is als de data in de db, maar dat hoeft niet het geval te zijn.

Lazy loading, prefetch paths etc. zijn bedoeld om data-load acties te optimaliseren.
Vanuit een performance perspectief is dit waarschijnlijk wel aan te raden (omdat je waarschijnlijk minder roundtrips naar de DB nodig hebt), maar je zult merken dat je donders goed in de gaten moet houden welke data wel, en welke data niet verouderd mag zijn. Als dit erg complex wordt, dan kan dat een argument zijn om deze performance-optimalisaties niet toe te passen, zodat je minder je hoofd hoeft te breken of je wel met (redelijk) actuele data werkt.
Alle data is per definitie 'verouderd'. Een 'beetje' verouderd is altijd nog 'verouderd', er is geen tussenweg. Overigens zijn roundtrips lang niet altijd de bottleneck.
Andersom is een DataSet ook niet inherent aan "problemen met verouderde data". Je kunt er nl. voor kiezen om een DataSet elke keer opnieuw in te lezen als je de betreffende data nodig hebt, en na elke wijziging op een DataSet deze meteen te laten doorvoeren op de database.
Dat helpt niets, dan nog werk je met stale data en dus loop je de kans op concurrency gerelateerde zaken.
De reden dat de DataSet vaak in 1 adem genoemd wordt met het risico op verouderde data, is (volgens mij) dat de DataSet gebaseerd is op de filosofie van "minimaliseer het aantal roundtrips naar de DB", en niet "houd de data in code zo consistent mogelijk met die in de DB". En dan is het risico op verouderde data meer aanwezig.
Welnee, de dataset is gewoon een untyped bak voor resultsets.
Ja en nee. Ja, het is beter om geen SQL in je business logic te gebruiken, en het is sowiezo een goed idee om stored procedures te gebruiken (de DB kan SP's doorgaans sneller uitvoeren dan losse SQL statements).
In het kader van onderhoudbaarheid is het inderdaad beter om geen SQL in de code te plaatsen, maar het is onzin dat sp's sneller uitgevoerd worden.
Dit kan je zowel met de combinatie DataSets + SPs als met een OR mapping bereiken, dus daar zit het verschil niet echt.
Zie mijn artikel hierboven over to O/R map or not to O/R map: het is wel degelijk een fundamenteel verschil of je datasets gebruikt of entity classes.

Stored procs icm een o/r mapper is lastig, want je mapt je entities dan op resultsets van procs ipv fysieke representaties van entity definities (tables/views).
[...]
Je hebt nu inmiddels denk ik wel door dat je vraag zou moeten zijn: "Gebruik ik wel of geen lazy loading en/of delayed writing?". ;)
Wat meespeelt in deze beslissing is:
- Hoeveel conflicten met verouderde data denk je tegen te komen? (zoals je al aangaf)
Dit heeft echt weinig met lazyloading te maken, omdat alle data die uit de db wordt geladen stale is.
- In hoeverre heb je de performancewinst van lazy loading en delayed writing nodig?
Lazy loading is alleen in DIE situatie een performance winst wanneer je enkele gerelateerde entities nodig hebt van een grote set. Wanneer je veel gerelateerde entities nodig hebt is lazy loading traag, omdat je per gerelateerd entity een query uitvoert.
- Welke data denk je veilig te kunnen cachen zonder in de problemen te komen?
Dit kun je ook buiten een O/R mapper doen en is veelal aan te raden. Zoals bv het cachen van webcontrols in een web applicatie: het cachen van de control output is efficienter dan het cachen van de entities gebruikt in de webcontrol, want je moet dan toch elke keer weer de control renderen, plus dat cache management performance KOST ipv dat het performance oplevert. (Entities cachen is alleen efficient wanneer je single entity instances fetcht op basis van de PK)
--toevoeging:--
Het gebruik van de concepten "lazy loading" (data pas inlezen als je het echt nodig hebt) en "delayed writing" (wijzigingen opsparen en dan als een bulk-opdracht naar de DB versturen) is meestal geen kwestie van wel of niet gebruiken, het is een spectrum.

De extreemste vormen zijn:
- altijd lazy loading (m.a.w. nooit geen data cachen)
- nooit lazy loading (alles van tevoren uitlezen en naar de client toetrekken (!!))
Je hebt ook nog zoiets als prefetch paths/spans: je wilt alle customers uit Nederland + hun 10 laatste orders. Dan heb je 2 queries nodig: de customers en de orders. Met lazy loading heb je dan (# customers)+1 queries nodig.

Lazy loading is overigens ook geen 'cache', het is een manier om het inladen van gerelateerde data uit te stellen, want wellicht heb je het niet nodig.
- alles delayed writen (bij het afsluiten van de applicatie pas DB-updates doen)
- nooit delayed writen (bij het aanpassen van een enkel veld meteen een update doen).
Alles delayed wegschrijven lijkt me onmogelijk, tenzij weggeschreven data niet opnieuw gelezen hoeft te worden.
Het moge duidelijk zijn dat (heel misschien met uitzondering van het 1e punt) dit geen werkbare oplossingen zijn. Een praktische oplossing ligt dus ergens in het midden, maar waar... dat verschilt per applicatie. :)
Nauwelijks, mits er goed gefilterd wordt, kun je altijd toe met prefetch paths.

[ Voor 75% gewijzigd door EfBe op 08-01-2007 12:48 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com

Pagina: 1